diff --git a/core/config/config_helper.cpp b/core/config/config_helper.cpp index 439060f5b41..1821e8a6c75 100644 --- a/core/config/config_helper.cpp +++ b/core/config/config_helper.cpp @@ -113,6 +113,18 @@ parse_minimal_criteria(const pnode& config, const registry& context, type_descriptor updated_td = update_type(config, td); + // Although it can still be caught in the following map, it gives consistent + // error exception when some keys are not allowed. + std::set allowed_keys{"time", + "iteration", + "relative_residual_norm", + "initial_residual_norm", + "absolute_residual_norm", + "relative_implicit_residual_norm", + "initial_implicit_residual_norm", + "absolute_implicit_residual_norm"}; + check_allowed_keys(config, allowed_keys); + std::vector> res; for (const auto& it : config.get_map()) { if (it.first == "value_type") { diff --git a/core/config/config_helper.hpp b/core/config/config_helper.hpp index c87c3e0cca7..f1017babe05 100644 --- a/core/config/config_helper.hpp +++ b/core/config/config_helper.hpp @@ -6,6 +6,7 @@ #define GKO_CORE_CONFIG_CONFIG_HELPER_HPP_ +#include #include #include @@ -312,6 +313,39 @@ inline std::shared_ptr get_strategy( } +// It is to check whether the keys of config (map type) are mentioned in +// allowed_keys. If not, it will throw an error message. +inline void check_allowed_keys(const pnode& config, + const std::set& allowed_keys) +{ + if (config.get_tag() != pnode::tag_t::map) { + // we only check the key in the map + return; + } + const auto& map = config.get_map(); + auto set_output = [](auto& set) { + std::string output = "["; + for (const auto& item : set) { + output = output + " " + item; + } + output += " ]"; + return output; + }; + for (const auto& item : map) { + if (item.first == "value_type" || item.first == "type") { + // We always allow value_type in any class and use type to choose + // the class + continue; + } + auto search = allowed_keys.find(item.first); + GKO_THROW_IF_INVALID( + search != allowed_keys.end(), + item.first + " is not a allowed key. The allowed keys here is " + + set_output(allowed_keys)); + } +} + + } // namespace config } // namespace gko diff --git a/core/config/solver_config.hpp b/core/config/solver_config.hpp index e2ed485a70c..1940b4a1f67 100644 --- a/core/config/solver_config.hpp +++ b/core/config/solver_config.hpp @@ -5,6 +5,8 @@ #ifndef GKO_CORE_CONFIG_SOLVER_CONFIG_HPP_ #define GKO_CORE_CONFIG_SOLVER_CONFIG_HPP_ +#include +#include #include #include @@ -17,9 +19,10 @@ namespace config { template -inline void common_solver_parse(SolverParam& params, const pnode& config, - const registry& context, - type_descriptor td_for_child) +inline std::set common_solver_parse(SolverParam& params, + const pnode& config, + const registry& context, + type_descriptor td_for_child) { if (auto& obj = config.get("generated_preconditioner")) { params.with_generated_preconditioner( @@ -34,6 +37,8 @@ inline void common_solver_parse(SolverParam& params, const pnode& config, gko::config::parse_or_get_factory( obj, context, td_for_child)); } + return std::set{"generated_preconditioner", "criteria", + "preconditioner"}; } diff --git a/core/config/stop_config.cpp b/core/config/stop_config.cpp index 4623eb768fc..b26a38bfae0 100644 --- a/core/config/stop_config.cpp +++ b/core/config/stop_config.cpp @@ -1,9 +1,12 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause #include "core/config/stop_config.hpp" +#include +#include + #include #include #include @@ -27,6 +30,8 @@ namespace config { deferred_factory_parameter configure_time( const pnode& config, const registry& context, const type_descriptor& td) { + std::set allowed_keys{"time_limit"}; + gko::config::check_allowed_keys(config, allowed_keys); auto params = stop::Time::build(); if (auto& obj = config.get("time_limit")) { params.with_time_limit(gko::config::get_value(obj)); @@ -38,6 +43,8 @@ deferred_factory_parameter configure_time( deferred_factory_parameter configure_iter( const pnode& config, const registry& context, const type_descriptor& td) { + std::set allowed_keys{"max_iters"}; + gko::config::check_allowed_keys(config, allowed_keys); auto params = stop::Iteration::build(); if (auto& obj = config.get("max_iters")) { params.with_max_iters(gko::config::get_value(obj)); @@ -68,6 +75,8 @@ class ResidualNormConfigurer { const gko::config::registry& context, const gko::config::type_descriptor& td_for_child) { + std::set allowed_keys{"reduction_factor", "baseline"}; + gko::config::check_allowed_keys(config, allowed_keys); auto params = stop::ResidualNorm::build(); if (auto& obj = config.get("reduction_factor")) { params.with_reduction_factor( @@ -100,6 +109,8 @@ class ImplicitResidualNormConfigurer { const gko::config::registry& context, const gko::config::type_descriptor& td_for_child) { + std::set allowed_keys{"reduction_factor", "baseline"}; + gko::config::check_allowed_keys(config, allowed_keys); auto params = stop::ImplicitResidualNorm::build(); if (auto& obj = config.get("reduction_factor")) { params.with_reduction_factor( diff --git a/core/config/trisolver_config.hpp b/core/config/trisolver_config.hpp index 8d7f6fb680d..f83ff008c6a 100644 --- a/core/config/trisolver_config.hpp +++ b/core/config/trisolver_config.hpp @@ -1,10 +1,12 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause #ifndef GKO_CORE_CONFIG_TRISOLVER_CONFIG_HPP_ #define GKO_CORE_CONFIG_TRISOLVER_CONFIG_HPP_ +#include +#include #include #include @@ -18,9 +20,9 @@ namespace config { template -inline void common_trisolver_parse(SolverParam& params, const pnode& config, - const registry& context, - type_descriptor td_for_child) +inline std::set common_trisolver_parse( + SolverParam& params, const pnode& config, const registry& context, + type_descriptor td_for_child) { if (auto& obj = config.get("num_rhs")) { params.with_num_rhs(gko::config::get_value(obj)); @@ -39,6 +41,7 @@ inline void common_trisolver_parse(SolverParam& params, const pnode& config, GKO_INVALID_CONFIG_VALUE("algorithm", str); } } + return {"num_rhs", "unit_diagonal", "algorithm"}; } diff --git a/core/distributed/preconditioner/schwarz.cpp b/core/distributed/preconditioner/schwarz.cpp index aba7598ad80..501c9ce8c6f 100644 --- a/core/distributed/preconditioner/schwarz.cpp +++ b/core/distributed/preconditioner/schwarz.cpp @@ -5,6 +5,8 @@ #include "ginkgo/core/distributed/preconditioner/schwarz.hpp" #include +#include +#include #include #include @@ -36,6 +38,9 @@ Schwarz::parse( const config::pnode& config, const config::registry& context, const config::type_descriptor& td_for_child) { + std::set allowed_keys{"generated_local_solver", + "local_solver"}; + gko::config::check_allowed_keys(config, allowed_keys); auto params = Schwarz::build(); if (auto& obj = config.get("generated_local_solver")) { diff --git a/core/factorization/cholesky.cpp b/core/factorization/cholesky.cpp index 2f8d8630a1e..e5a1372b98d 100644 --- a/core/factorization/cholesky.cpp +++ b/core/factorization/cholesky.cpp @@ -4,6 +4,9 @@ #include "ginkgo/core/factorization/cholesky.hpp" +#include +#include + #include #include #include @@ -42,6 +45,9 @@ Cholesky::parse( const config::pnode& config, const config::registry& context, const config::type_descriptor& td_for_child) { + std::set allowed_keys{"symbolic_factorization", + "skip_sorting"}; + gko::config::check_allowed_keys(config, allowed_keys); auto params = Cholesky::build(); if (auto& obj = config.get("symbolic_factorization")) { params.with_symbolic_factorization( diff --git a/core/factorization/ic.cpp b/core/factorization/ic.cpp index 3eb14e05a4a..d12b1e8609f 100644 --- a/core/factorization/ic.cpp +++ b/core/factorization/ic.cpp @@ -5,6 +5,8 @@ #include "ginkgo/core/factorization/ic.hpp" #include +#include +#include #include #include @@ -53,6 +55,9 @@ Ic::parse(const config::pnode& config, const config::registry& context, const config::type_descriptor& td_for_child) { + std::set allowed_keys{"l_strategy", "skip_sorting", + "both_factors", "algorithm"}; + gko::config::check_allowed_keys(config, allowed_keys); auto params = factorization::Ic::build(); if (auto& obj = config.get("l_strategy")) { params.with_l_strategy(config::get_strategy(obj)); diff --git a/core/factorization/ilu.cpp b/core/factorization/ilu.cpp index c865a15c261..2435f04b646 100644 --- a/core/factorization/ilu.cpp +++ b/core/factorization/ilu.cpp @@ -5,6 +5,8 @@ #include "ginkgo/core/factorization/ilu.hpp" #include +#include +#include #include #include @@ -50,6 +52,9 @@ Ilu::parse(const config::pnode& config, const config::registry& context, const config::type_descriptor& td_for_child) { + std::set allowed_keys{"l_strategy", "u_strategy", + "skip_sorting", "algorithm"}; + gko::config::check_allowed_keys(config, allowed_keys); auto params = factorization::Ilu::build(); if (auto& obj = config.get("l_strategy")) { params.with_l_strategy(config::get_strategy(obj)); diff --git a/core/factorization/lu.cpp b/core/factorization/lu.cpp index 7811ae0ba0c..b3de47cf451 100644 --- a/core/factorization/lu.cpp +++ b/core/factorization/lu.cpp @@ -4,6 +4,9 @@ #include "ginkgo/core/factorization/lu.hpp" +#include +#include + #include #include #include @@ -43,6 +46,9 @@ Lu::parse(const config::pnode& config, const config::registry& context, const config::type_descriptor& td_for_child) { + std::set allowed_keys{"symbolic_factorization", + "symbolic_algorithm", "skip_sorting"}; + gko::config::check_allowed_keys(config, allowed_keys); auto params = experimental::factorization::Lu::build(); diff --git a/core/factorization/par_ic.cpp b/core/factorization/par_ic.cpp index f4a4afd23d6..b09fe9ef015 100644 --- a/core/factorization/par_ic.cpp +++ b/core/factorization/par_ic.cpp @@ -1,10 +1,12 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause #include "ginkgo/core/factorization/par_ic.hpp" #include +#include +#include #include #include @@ -51,6 +53,9 @@ ParIc::parse(const config::pnode& config, const config::registry& context, const config::type_descriptor& td_for_child) { + std::set allowed_keys{"iterations", "skip_sorting", + "l_strategy", "both_factors"}; + gko::config::check_allowed_keys(config, allowed_keys); auto params = factorization::ParIc::build(); if (auto& obj = config.get("iterations")) { diff --git a/core/factorization/par_ict.cpp b/core/factorization/par_ict.cpp index a0e8a628ca8..b769de1f814 100644 --- a/core/factorization/par_ict.cpp +++ b/core/factorization/par_ict.cpp @@ -1,10 +1,12 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause #include "ginkgo/core/factorization/par_ict.hpp" #include +#include +#include #include #include @@ -150,6 +152,11 @@ ParIct::parse(const config::pnode& config, const config::registry& context, const config::type_descriptor& td_for_child) { + std::set allowed_keys{ + "iterations", "skip_sorting", "approximate_select", + "deterministic_sample", "fill_in_limit", "l_strategy", + "lt_strategy"}; + gko::config::check_allowed_keys(config, allowed_keys); auto params = factorization::ParIct::build(); if (auto& obj = config.get("iterations")) { diff --git a/core/factorization/par_ilu.cpp b/core/factorization/par_ilu.cpp index 68c0c0c4fc6..def6239cc63 100644 --- a/core/factorization/par_ilu.cpp +++ b/core/factorization/par_ilu.cpp @@ -1,10 +1,12 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause #include "ginkgo/core/factorization/par_ilu.hpp" #include +#include +#include #include #include @@ -48,6 +50,9 @@ ParIlu::parse(const config::pnode& config, const config::registry& context, const config::type_descriptor& td_for_child) { + std::set allowed_keys{"iterations", "skip_sorting", + "l_strategy", "u_strategy"}; + gko::config::check_allowed_keys(config, allowed_keys); auto params = factorization::ParIlu::build(); if (auto& obj = config.get("iterations")) { diff --git a/core/factorization/par_ilut.cpp b/core/factorization/par_ilut.cpp index 42e3cc03130..d2e4458217e 100644 --- a/core/factorization/par_ilut.cpp +++ b/core/factorization/par_ilut.cpp @@ -1,10 +1,12 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause #include "ginkgo/core/factorization/par_ilut.hpp" #include +#include +#include #include #include @@ -166,6 +168,12 @@ ParIlut::parse( const config::pnode& config, const config::registry& context, const config::type_descriptor& td_for_child) { + std::set allowed_keys{ + "iterations", "skip_sorting", + "approximate_select", "deterministic_sample", + "fill_in_limit", "l_strategy", + "u_strategy"}; + gko::config::check_allowed_keys(config, allowed_keys); auto params = factorization::ParIlut::build(); if (auto& obj = config.get("iterations")) { diff --git a/core/multigrid/pgm.cpp b/core/multigrid/pgm.cpp index a6fac943db9..d70df7de498 100644 --- a/core/multigrid/pgm.cpp +++ b/core/multigrid/pgm.cpp @@ -4,6 +4,9 @@ #include "ginkgo/core/multigrid/pgm.hpp" +#include +#include + #include #include #include @@ -145,6 +148,9 @@ Pgm::parse(const config::pnode& config, const config::registry& context, const config::type_descriptor& td_for_child) { + std::set allowed_keys{"max_iterations", "max_unassigned_ratio", + "deterministic", "skip_sorting"}; + gko::config::check_allowed_keys(config, allowed_keys); auto params = Pgm::build(); if (auto& obj = config.get("max_iterations")) { params.with_max_iterations(gko::config::get_value(obj)); diff --git a/core/preconditioner/gauss_seidel.cpp b/core/preconditioner/gauss_seidel.cpp index aec7a4ff827..10cf1e30acf 100644 --- a/core/preconditioner/gauss_seidel.cpp +++ b/core/preconditioner/gauss_seidel.cpp @@ -1,8 +1,12 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause -#include +#include "ginkgo/core/preconditioner/gauss_seidel.hpp" + +#include +#include + #include #include "core/config/config_helper.hpp" @@ -18,6 +22,10 @@ GaussSeidel::parse( const config::pnode& config, const config::registry& context, const config::type_descriptor& td_for_child) { + std::set allowed_keys{"skip_sorting", "symmetric", "l_solver", + "u_solver"}; + gko::config::check_allowed_keys(config, allowed_keys); + auto params = GaussSeidel::build(); if (auto& obj = config.get("skip_sorting")) { diff --git a/core/preconditioner/ic.cpp b/core/preconditioner/ic.cpp index 691795ad60b..011214971aa 100644 --- a/core/preconditioner/ic.cpp +++ b/core/preconditioner/ic.cpp @@ -1,9 +1,12 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause #include "ginkgo/core/preconditioner/ic.hpp" +#include +#include + #include #include #include @@ -27,6 +30,9 @@ typename Ic::parameters_type ic_parse( const config::pnode& config, const config::registry& context, const config::type_descriptor& td_for_child) { + std::set allowed_keys{"l_solver", "factorization"}; + gko::config::check_allowed_keys(config, allowed_keys); + auto params = Ic::build(); if (auto& obj = config.get("l_solver")) { diff --git a/core/preconditioner/ilu.cpp b/core/preconditioner/ilu.cpp index d6f49e49588..797f16eb0fb 100644 --- a/core/preconditioner/ilu.cpp +++ b/core/preconditioner/ilu.cpp @@ -1,9 +1,12 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause #include "ginkgo/core/preconditioner/ilu.hpp" +#include +#include + #include #include #include @@ -29,6 +32,9 @@ typename Ilu::parameters_type ilu_parse( const config::pnode& config, const config::registry& context, const config::type_descriptor& td_for_child) { + std::set allowed_keys{"l_solver", "u_solver", "factorization"}; + gko::config::check_allowed_keys(config, allowed_keys); + auto params = Ilu::build(); if (auto& obj = config.get("l_solver")) { diff --git a/core/preconditioner/isai.cpp b/core/preconditioner/isai.cpp index 9684f1bdb27..03e8b5325cb 100644 --- a/core/preconditioner/isai.cpp +++ b/core/preconditioner/isai.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause @@ -6,6 +6,8 @@ #include #include +#include +#include #include #include @@ -98,6 +100,11 @@ Isai::parse( const config::pnode& config, const config::registry& context, const config::type_descriptor& td_for_child) { + std::set allowed_keys{"skip_sorting", "sparsity_power", + "excess_limit", "excess_solver_factory", + "excess_solver_reduction"}; + gko::config::check_allowed_keys(config, allowed_keys); + auto params = preconditioner::Isai::build(); if (auto& obj = config.get("skip_sorting")) { diff --git a/core/preconditioner/jacobi.cpp b/core/preconditioner/jacobi.cpp index 1164f6c0cb8..677ef092fe7 100644 --- a/core/preconditioner/jacobi.cpp +++ b/core/preconditioner/jacobi.cpp @@ -1,10 +1,12 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause #include "ginkgo/core/preconditioner/jacobi.hpp" #include +#include +#include #include #include @@ -57,6 +59,11 @@ Jacobi::parse(const config::pnode& config, const config::registry& context, const config::type_descriptor& td_for_child) { + std::set allowed_keys{ + "max_block_size", "max_block_stride", "skip_sorting", + "block_pointers", "storage_optimization", "accuracy"}; + gko::config::check_allowed_keys(config, allowed_keys); + auto params = preconditioner::Jacobi::build(); if (auto& obj = config.get("max_block_size")) { diff --git a/core/preconditioner/sor.cpp b/core/preconditioner/sor.cpp index c9905c5f73c..2bc6b88281c 100644 --- a/core/preconditioner/sor.cpp +++ b/core/preconditioner/sor.cpp @@ -1,13 +1,17 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause +#include "ginkgo/core/preconditioner/sor.hpp" + +#include +#include + #include #include #include #include #include -#include #include #include "core/base/array_access.hpp" @@ -39,6 +43,11 @@ Sor::parse(const config::pnode& config, const config::registry& context, const config::type_descriptor& td_for_child) { + std::set allowed_keys{"skip_sorting", "symmetric", + "relaxation_factor", "l_solver", + "u_solver"}; + gko::config::check_allowed_keys(config, allowed_keys); + auto params = Sor::build(); if (auto& obj = config.get("skip_sorting")) { diff --git a/core/solver/bicg.cpp b/core/solver/bicg.cpp index 0b39b3664cc..43105f4274d 100644 --- a/core/solver/bicg.cpp +++ b/core/solver/bicg.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause @@ -11,6 +11,7 @@ #include #include +#include "core/config/config_helper.hpp" #include "core/config/solver_config.hpp" #include "core/solver/bicg_kernels.hpp" #include "core/solver/solver_boilerplate.hpp" @@ -37,7 +38,9 @@ typename Bicg::parameters_type Bicg::parse( const config::type_descriptor& td_for_child) { auto params = solver::Bicg::build(); - common_solver_parse(params, config, context, td_for_child); + auto allowed_keys = + common_solver_parse(params, config, context, td_for_child); + gko::config::check_allowed_keys(config, allowed_keys); return params; } diff --git a/core/solver/bicgstab.cpp b/core/solver/bicgstab.cpp index c254b417765..1b043537e57 100644 --- a/core/solver/bicgstab.cpp +++ b/core/solver/bicgstab.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause @@ -12,6 +12,7 @@ #include #include +#include "core/config/config_helper.hpp" #include "core/config/solver_config.hpp" #include "core/distributed/helpers.hpp" #include "core/solver/bicgstab_kernels.hpp" @@ -41,7 +42,9 @@ typename Bicgstab::parameters_type Bicgstab::parse( const config::type_descriptor& td_for_child) { auto params = solver::Bicgstab::build(); - common_solver_parse(params, config, context, td_for_child); + auto allowed_keys = + common_solver_parse(params, config, context, td_for_child); + gko::config::check_allowed_keys(config, allowed_keys); return params; } diff --git a/core/solver/cb_gmres.cpp b/core/solver/cb_gmres.cpp index 1de3a79fb7c..b36aff4079f 100644 --- a/core/solver/cb_gmres.cpp +++ b/core/solver/cb_gmres.cpp @@ -1,9 +1,11 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause #include "ginkgo/core/solver/cb_gmres.hpp" +#include +#include #include #include @@ -17,6 +19,7 @@ #include #include "core/base/extended_float.hpp" +#include "core/config/config_helper.hpp" #include "core/config/solver_config.hpp" #include "core/solver/cb_gmres_accessor.hpp" #include "core/solver/cb_gmres_kernels.hpp" @@ -162,7 +165,11 @@ typename CbGmres::parameters_type CbGmres::parse( const config::type_descriptor& td_for_child) { auto params = solver::CbGmres::build(); - common_solver_parse(params, config, context, td_for_child); + auto allowed_keys = + common_solver_parse(params, config, context, td_for_child); + std::set other_keys{"krylov_dim", "storage_precision"}; + allowed_keys.merge(other_keys); + gko::config::check_allowed_keys(config, allowed_keys); if (auto& obj = config.get("krylov_dim")) { params.with_krylov_dim(gko::config::get_value(obj)); } diff --git a/core/solver/cg.cpp b/core/solver/cg.cpp index c512dc4313b..7aa1c561b24 100644 --- a/core/solver/cg.cpp +++ b/core/solver/cg.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause @@ -12,6 +12,7 @@ #include #include +#include "core/config/config_helper.hpp" #include "core/config/solver_config.hpp" #include "core/distributed/helpers.hpp" #include "core/solver/cg_kernels.hpp" @@ -39,7 +40,9 @@ typename Cg::parameters_type Cg::parse( const config::type_descriptor& td_for_child) { auto params = solver::Cg::build(); - common_solver_parse(params, config, context, td_for_child); + auto allowed_keys = + common_solver_parse(params, config, context, td_for_child); + gko::config::check_allowed_keys(config, allowed_keys); return params; } diff --git a/core/solver/cgs.cpp b/core/solver/cgs.cpp index 19f625228a3..187071a50fa 100644 --- a/core/solver/cgs.cpp +++ b/core/solver/cgs.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause @@ -12,6 +12,7 @@ #include #include +#include "core/config/config_helper.hpp" #include "core/config/solver_config.hpp" #include "core/distributed/helpers.hpp" #include "core/solver/cgs_kernels.hpp" @@ -40,7 +41,9 @@ typename Cgs::parameters_type Cgs::parse( const config::type_descriptor& td_for_child) { auto params = solver::Cgs::build(); - common_solver_parse(params, config, context, td_for_child); + auto allowed_keys = + common_solver_parse(params, config, context, td_for_child); + gko::config::check_allowed_keys(config, allowed_keys); return params; } diff --git a/core/solver/direct.cpp b/core/solver/direct.cpp index cf15bc4a9ae..7a5f74bb5a4 100644 --- a/core/solver/direct.cpp +++ b/core/solver/direct.cpp @@ -1,10 +1,12 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause #include "ginkgo/core/solver/direct.hpp" #include +#include +#include #include #include @@ -25,6 +27,8 @@ Direct::parse(const config::pnode& config, const config::type_descriptor& td_for_child) { auto params = Direct::build(); + std::set allowed_keys{"num_rhs", "factorization"}; + gko::config::check_allowed_keys(config, allowed_keys); if (auto& obj = config.get("num_rhs")) { params.with_num_rhs(gko::config::get_value(obj)); } diff --git a/core/solver/fcg.cpp b/core/solver/fcg.cpp index 6c65f63ccae..1d768465344 100644 --- a/core/solver/fcg.cpp +++ b/core/solver/fcg.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause @@ -11,6 +11,7 @@ #include #include +#include "core/config/config_helper.hpp" #include "core/config/solver_config.hpp" #include "core/distributed/helpers.hpp" #include "core/solver/fcg_kernels.hpp" @@ -38,7 +39,9 @@ typename Fcg::parameters_type Fcg::parse( const config::type_descriptor& td_for_child) { auto params = solver::Fcg::build(); - common_solver_parse(params, config, context, td_for_child); + auto allowed_keys = + common_solver_parse(params, config, context, td_for_child); + gko::config::check_allowed_keys(config, allowed_keys); return params; } diff --git a/core/solver/gcr.cpp b/core/solver/gcr.cpp index d5131632dc3..5ffff29c068 100644 --- a/core/solver/gcr.cpp +++ b/core/solver/gcr.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause @@ -14,6 +14,7 @@ #include #include +#include "core/config/config_helper.hpp" #include "core/config/solver_config.hpp" #include "core/distributed/helpers.hpp" #include "core/solver/gcr_kernels.hpp" @@ -41,7 +42,10 @@ typename Gcr::parameters_type Gcr::parse( const config::type_descriptor& td_for_child) { auto params = solver::Gcr::build(); - common_solver_parse(params, config, context, td_for_child); + auto allowed_keys = + common_solver_parse(params, config, context, td_for_child); + allowed_keys.insert("krylov_dim"); + gko::config::check_allowed_keys(config, allowed_keys); if (auto& obj = config.get("krylov_dim")) { params.with_krylov_dim(gko::config::get_value(obj)); } diff --git a/core/solver/gmres.cpp b/core/solver/gmres.cpp index f2bd5893a41..8070c8d9a39 100644 --- a/core/solver/gmres.cpp +++ b/core/solver/gmres.cpp @@ -4,6 +4,9 @@ #include "ginkgo/core/solver/gmres.hpp" +#include +#include + #include #include #include @@ -15,6 +18,7 @@ #include #include +#include "core/config/config_helper.hpp" #include "core/config/solver_config.hpp" #include "core/distributed/helpers.hpp" #include "core/mpi/mpi_op.hpp" @@ -63,7 +67,11 @@ typename Gmres::parameters_type Gmres::parse( const config::type_descriptor& td_for_child) { auto params = solver::Gmres::build(); - common_solver_parse(params, config, context, td_for_child); + auto allowed_keys = + common_solver_parse(params, config, context, td_for_child); + std::set other_keys{"krylov_dim", "flexible", "ortho_method"}; + allowed_keys.merge(other_keys); + gko::config::check_allowed_keys(config, allowed_keys); if (auto& obj = config.get("krylov_dim")) { params.with_krylov_dim(gko::config::get_value(obj)); } diff --git a/core/solver/idr.cpp b/core/solver/idr.cpp index b10c15136f4..ae75385c007 100644 --- a/core/solver/idr.cpp +++ b/core/solver/idr.cpp @@ -1,9 +1,12 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause #include "ginkgo/core/solver/idr.hpp" +#include +#include + #include #include #include @@ -11,6 +14,7 @@ #include #include +#include "core/config/config_helper.hpp" #include "core/config/solver_config.hpp" #include "core/distributed/helpers.hpp" #include "core/solver/idr_kernels.hpp" @@ -40,7 +44,12 @@ typename Idr::parameters_type Idr::parse( const config::type_descriptor& td_for_child) { auto params = solver::Idr::build(); - common_solver_parse(params, config, context, td_for_child); + auto allowed_keys = + common_solver_parse(params, config, context, td_for_child); + std::set other_keys{"subspace_dim", "kappa", "deterministic", + "complex_subspace"}; + allowed_keys.merge(other_keys); + gko::config::check_allowed_keys(config, allowed_keys); if (auto& obj = config.get("subspace_dim")) { params.with_subspace_dim(gko::config::get_value(obj)); } diff --git a/core/solver/ir.cpp b/core/solver/ir.cpp index 75efac351f9..22d0fd703d5 100644 --- a/core/solver/ir.cpp +++ b/core/solver/ir.cpp @@ -1,9 +1,12 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause #include "ginkgo/core/solver/ir.hpp" +#include +#include + #include #include #include @@ -34,6 +37,10 @@ typename Ir::parameters_type Ir::parse( const config::type_descriptor& td_for_child) { auto params = solver::Ir::build(); + std::set allowed_keys{"criteria", "solver", "generated_solver", + "relaxation_factor", + "default_initial_guess"}; + gko::config::check_allowed_keys(config, allowed_keys); if (auto& obj = config.get("criteria")) { params.with_criteria( gko::config::parse_or_get_factory_vector< diff --git a/core/solver/lower_trs.cpp b/core/solver/lower_trs.cpp index 3048c877dbd..cd5d1a59f19 100644 --- a/core/solver/lower_trs.cpp +++ b/core/solver/lower_trs.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause @@ -41,7 +41,9 @@ LowerTrs::parse( const config::type_descriptor& td_for_child) { auto params = LowerTrs::build(); - common_trisolver_parse(params, config, context, td_for_child); + auto allowed_keys = + common_trisolver_parse(params, config, context, td_for_child); + gko::config::check_allowed_keys(config, allowed_keys); return params; } diff --git a/core/solver/multigrid.cpp b/core/solver/multigrid.cpp index cbbcd028128..a7f2bf17908 100644 --- a/core/solver/multigrid.cpp +++ b/core/solver/multigrid.cpp @@ -5,6 +5,8 @@ #include "ginkgo/core/solver/multigrid.hpp" #include +#include +#include #include #include @@ -606,6 +608,16 @@ typename Multigrid::parameters_type Multigrid::parse( { auto params = Multigrid::build(); + std::set allowed_keys{ + "criteria", "mg_level", + "pre_smoother", "post_smoother", + "mid_smoother", "post_uses_pre", + "mid_case", "max_levels", + "min_coarse_rows", "coarsest_solver", + "cycle", "kcycle_base", + "kcycle_rel_tol", "smoother_relax", + "smoother_iters", "default_initial_guess"}; + gko::config::check_allowed_keys(config, allowed_keys); if (auto& obj = config.get("criteria")) { params.with_criteria( config::parse_or_get_factory_vector( diff --git a/core/solver/upper_trs.cpp b/core/solver/upper_trs.cpp index c759c119647..9ea178424cc 100644 --- a/core/solver/upper_trs.cpp +++ b/core/solver/upper_trs.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause @@ -41,7 +41,9 @@ UpperTrs::parse( const config::type_descriptor& td_for_child) { auto params = UpperTrs::build(); - common_trisolver_parse(params, config, context, td_for_child); + auto allowed_keys = + common_trisolver_parse(params, config, context, td_for_child); + gko::config::check_allowed_keys(config, allowed_keys); return params; } diff --git a/core/test/config/config.cpp b/core/test/config/config.cpp index ba3aae2453f..9922c879895 100644 --- a/core/test/config/config.cpp +++ b/core/test/config/config.cpp @@ -4,6 +4,7 @@ #include +#include #include #include #include @@ -123,6 +124,26 @@ TEST_F(Config, GenerateObjectWithCustomBuild) } +TEST_F(Config, ThrowWhenKeyIsInvalidInCriterion) +{ + auto reg = registry(); + reg.emplace("precond", this->mtx); + + for (const auto& stop : + {"Time", "Iteration", "ResidualNorm", "ImplicitResidualNorm"}) { + pnode stop_config{ + {{"type", pnode{stop}}, {"invalid_key", pnode{"no"}}}}; + pnode p{{{"generated_preconditioner", pnode{"precond"}}, + {"criteria", stop_config}}}; + + ASSERT_THROW(parse( + p, reg, type_descriptor{"float32", "void"}) + .on(this->exec), + gko::InvalidStateError); + } +} + + TEST_F(Config, GenerateCriteriaFromMinimalConfig) { // the map is ordered, since this allows for easier comparison in the test @@ -256,6 +277,18 @@ TEST_F(Config, GenerateCriteriaFromMinimalConfigWithValueType) } +TEST_F(Config, MinimalConfigThrowWhenKeyIsInvalid) +{ + pnode minimal_stop{{{"time", pnode{100}}, {"invalid", pnode{"no"}}}}; + pnode p{{{"criteria", minimal_stop}}}; + + ASSERT_THROW(parse(p, registry(), + type_descriptor{"float32", "void"}) + .on(this->exec), + gko::InvalidStateError); +} + + TEST(GetValue, IndexType) { long long int value = 123; diff --git a/core/test/config/factorization.cpp b/core/test/config/factorization.cpp index 1391787437a..0cf285a15a4 100644 --- a/core/test/config/factorization.cpp +++ b/core/test/config/factorization.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause @@ -420,6 +420,18 @@ TYPED_TEST(Factorization, CreateDefault) } +TYPED_TEST(Factorization, ThrowWhenKeyIsNotAllowed) +{ + using Config = typename TestFixture::Config; + auto pnode_map = Config::setup_base(); + pnode_map["invalid_key"] = pnode{""}; + auto config = pnode(pnode_map); + + ASSERT_THROW(parse(config, this->reg, this->td).on(this->exec), + gko::InvalidStateError); +} + + TYPED_TEST(Factorization, ExplicitTemplate) { using Config = typename TestFixture::Config; diff --git a/core/test/config/multigrid.cpp b/core/test/config/multigrid.cpp index 5eb8e622088..963fc63f9be 100644 --- a/core/test/config/multigrid.cpp +++ b/core/test/config/multigrid.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause @@ -104,6 +104,18 @@ TYPED_TEST(MultigridLevel, CreateDefault) } +TYPED_TEST(MultigridLevel, ThrowWhenKeyIsNotAllowed) +{ + using Config = typename TestFixture::Config; + auto pnode_map = Config::setup_base(); + pnode_map["invalid_key"] = pnode{""}; + auto config = pnode(pnode_map); + + ASSERT_THROW(parse(config, this->reg, this->td).on(this->exec), + gko::InvalidStateError); +} + + TYPED_TEST(MultigridLevel, ExplicitTemplate) { using Config = typename TestFixture::Config; @@ -328,6 +340,18 @@ TEST_F(MultigridT, CreateDefault) } +TYPED_TEST(MultigridT, ThrowWhenKeyIsNotAllowed) +{ + using Config = typename TestFixture::Config; + auto pnode_map = Config::setup_base(); + pnode_map["invalid_key"] = pnode{""}; + auto config = pnode(pnode_map); + + ASSERT_THROW(parse(config, this->reg, this->td).on(this->exec), + gko::InvalidStateError); +} + + TEST_F(MultigridT, SetFromRegistry) { auto config_map = Config::setup_base(); diff --git a/core/test/config/preconditioner.cpp b/core/test/config/preconditioner.cpp index c603aaea750..02a5f9afe02 100644 --- a/core/test/config/preconditioner.cpp +++ b/core/test/config/preconditioner.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause @@ -514,6 +514,18 @@ TYPED_TEST(Preconditioner, CreateDefault) } +TYPED_TEST(Preconditioner, ThrowWhenKeyIsNotAllowed) +{ + using Config = typename TestFixture::Config; + auto pnode_map = Config::setup_base(); + pnode_map["invalid_key"] = pnode{""}; + auto config = pnode(pnode_map); + + ASSERT_THROW(parse(config, this->reg, this->td).on(this->exec), + gko::InvalidStateError); +} + + TYPED_TEST(Preconditioner, ExplicitTemplate) { using Config = typename TestFixture::Config; diff --git a/core/test/config/solver.cpp b/core/test/config/solver.cpp index a170ebb1e04..8d313a3b045 100644 --- a/core/test/config/solver.cpp +++ b/core/test/config/solver.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors // // SPDX-License-Identifier: BSD-3-Clause @@ -6,6 +6,7 @@ #include +#include #include #include #include @@ -486,6 +487,18 @@ TYPED_TEST(Solver, CreateDefault) } +TYPED_TEST(Solver, ThrowWhenKeyIsNotAllowed) +{ + using Config = typename TestFixture::Config; + auto pnode_map = Config::setup_base(); + pnode_map["invalid_key"] = pnode{""}; + auto config = pnode(pnode_map); + + ASSERT_THROW(parse(config, this->reg, this->td).on(this->exec), + gko::InvalidStateError); +} + + TYPED_TEST(Solver, ExplicitTemplate) { using Config = typename TestFixture::Config;