Skip to content

Allow to use ValueType in template of preconditioner ILU #1828

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cmake/CTestScript.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,9 @@ ctest_submit(PARTS Start)

if(CTEST_MEMORYCHECK_TYPE STREQUAL "CudaMemcheck")
# generate line number information for CUDA
# we disable bfloat16 because our job is executed on the gpu does not support bfloat16 natively
set(GINKGO_CONFIGURE_OPTIONS
"-DGINKGO_DEVEL_TOOLS=OFF;-DGINKGO_BUILD_REFERENCE=ON;-DGINKGO_BUILD_OMP=OFF;-DGINKGO_BUILD_CUDA=ON;-DGINKGO_BUILD_HIP=OFF;-DGINKGO_BUILD_SYCL=OFF;-DCMAKE_BUILD_TYPE=${CTEST_BUILD_CONFIGURATION};-DCMAKE_CUDA_FLAGS=-lineinfo"
"-DGINKGO_ENABLE_BFLOAT16=OFF;-DGINKGO_DEVEL_TOOLS=OFF;-DGINKGO_BUILD_REFERENCE=ON;-DGINKGO_BUILD_OMP=OFF;-DGINKGO_BUILD_CUDA=ON;-DGINKGO_BUILD_HIP=OFF;-DGINKGO_BUILD_SYCL=OFF;-DCMAKE_BUILD_TYPE=${CTEST_BUILD_CONFIGURATION};-DCMAKE_CUDA_FLAGS=-lineinfo"
)
elseif(
(
Expand Down
1 change: 1 addition & 0 deletions cmake/generate_ginkgo_hpp.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ function(ginkgo_generate_ginkgo_hpp)
(file MATCHES "^ginkgo/extensions/.*$")
OR (file MATCHES "^ginkgo/core/stop/residual_norm_reduction.hpp$")
OR (file MATCHES "^ginkgo/core/solver/.*_trs.hpp$")
OR (file MATCHES "^ginkgo/core/preconditioner/utils.hpp$")
)
continue()
endif()
Expand Down
6 changes: 3 additions & 3 deletions core/config/preconditioner_ic_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ parse<gko::config::LinOpFactoryType::Ic>(const gko::config::pnode& config,
if (config.get("l_solver_type_or_value_type")) {
GKO_INVALID_STATE(
"preconditioner::Ic only allows value_type from "
"l_solver_type_or_value_type. To avoid type confusion between "
"these types and value_type, l_solver_type_or_value_type uses "
"the value_type directly.");
"l_solver_type_or_value_type. Please use value_type key to set the "
"value type used by the preconditioner and the l_lover key to set "
"the solvers used for the lower triangular systems.");
}
return gko::config::dispatch<gko::LinOpFactory, gko::preconditioner::Ic>(
config, context, updated,
Expand Down
118 changes: 22 additions & 96 deletions core/config/preconditioner_ilu_config.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +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/base/exception_helpers.hpp>
#include <ginkgo/core/config/config.hpp>
#include <ginkgo/core/config/registry.hpp>
#include <ginkgo/core/preconditioner/ic.hpp>
#include <ginkgo/core/preconditioner/ilu.hpp>
#include <ginkgo/core/preconditioner/isai.hpp>
#include <ginkgo/core/solver/gmres.hpp>
#include <ginkgo/core/solver/ir.hpp>
#include <ginkgo/core/solver/triangular.hpp>

#include "core/config/config_helper.hpp"
#include "core/config/dispatch.hpp"
Expand All @@ -22,123 +17,54 @@
namespace config {


// For Ic and Ilu, we use additional ValueType to help Solver type decision
template <typename LSolver, typename USolver, bool ReverseApply>
template <bool ReverseApply>
class IluSolverHelper {
public:
template <typename ValueType, typename IndexType>
class Configurator {
public:
static typename preconditioner::Ilu<LSolver, USolver, ReverseApply,
static typename preconditioner::Ilu<ValueType, ValueType, ReverseApply,
IndexType>::parameters_type
parse(const pnode& config, const registry& context,
const type_descriptor& td_for_child)
{
return preconditioner::Ilu<LSolver, USolver, ReverseApply,
return preconditioner::Ilu<ValueType, ValueType, ReverseApply,
IndexType>::parse(config, context,
td_for_child);
}
};
};


template <template <typename V> class LSolverBase,
template <typename V> class USolverBase, bool ReverseApply>
class IluHelper1 {
public:
template <typename ValueType, typename IndexType>
class Configurator
: public IluSolverHelper<
LSolverBase<ValueType>, USolverBase<ValueType>,
ReverseApply>::template Configurator<ValueType, IndexType> {};
};


template <template <typename V, typename I> class LSolverBase,
template <typename V, typename I> class USolverBase,
bool ReverseApply>
class IluHelper2 {
public:
template <typename ValueType, typename IndexType>
class Configurator
: public IluSolverHelper<
LSolverBase<ValueType, IndexType>,
USolverBase<ValueType, IndexType>,
ReverseApply>::template Configurator<ValueType, IndexType> {};
};


template <>
deferred_factory_parameter<gko::LinOpFactory> parse<LinOpFactoryType::Ilu>(
const pnode& config, const registry& context, const type_descriptor& td)
{
auto updated = update_type(config, td);
auto dispatch_solver = [&](auto reverse_apply)
-> deferred_factory_parameter<gko::LinOpFactory> {
using ReverseApply = decltype(reverse_apply);
// always use symmetric solver for USolverType
if (config.get("u_solver_type")) {
GKO_INVALID_STATE(
"preconditioner::Ilu only allows l_solver_type. The "
"u_solver_type automatically uses the transposed type of "
"l_solver_type.");
}
std::string str("solver::LowerTrs");
if (auto& obj = config.get("l_solver_type")) {
str = obj.get_string();
}
if (str == "solver::LowerTrs") {
return dispatch<
gko::LinOpFactory,
IluHelper2<solver::LowerTrs, solver::UpperTrs,
ReverseApply::value>::template Configurator>(
config, context, updated,
make_type_selector(updated.get_value_typestr(),
value_type_list()),
make_type_selector(updated.get_index_typestr(),
index_type_list()));
} else if (str == "solver::Ir") {
return dispatch<
gko::LinOpFactory,
IluHelper1<solver::Ir, solver::Ir,
ReverseApply::value>::template Configurator>(
config, context, updated,
make_type_selector(updated.get_value_typestr(),
value_type_list()),
make_type_selector(updated.get_index_typestr(),
index_type_list()));
} else if (str == "preconditioner::LowerIsai") {
return dispatch<
gko::LinOpFactory,
IluHelper2<preconditioner::LowerIsai, preconditioner::UpperIsai,
ReverseApply::value>::template Configurator>(
config, context, updated,
make_type_selector(updated.get_value_typestr(),
value_type_list()),
make_type_selector(updated.get_index_typestr(),
index_type_list()));
} else if (str == "solver::Gmres") {
return dispatch<
gko::LinOpFactory,
IluHelper1<solver::Gmres, solver::Gmres,
ReverseApply::value>::template Configurator>(
config, context, updated,
make_type_selector(updated.get_value_typestr(),
value_type_list()),
make_type_selector(updated.get_index_typestr(),
index_type_list()));
} else {
GKO_INVALID_CONFIG_VALUE("l_solver_type", str);
}
};
if (config.get("l_solver_type_or_value_type") ||
config.get("u_solver_type_or_value_type")) {
GKO_INVALID_STATE(

Check warning on line 46 in core/config/preconditioner_ilu_config.cpp

View check run for this annotation

Codecov / codecov/patch

core/config/preconditioner_ilu_config.cpp#L46

Added line #L46 was not covered by tests
"preconditioner::Ilu only allows value_type from "
"l_solver_type_or_value_type/u_solver_type_or_value_type. Please "
"use value_type key to set the value type used by the "
"preconditioner and the l_lover or u_solver key to set the solvers "
"used for the lower and upper triangular systems.");
}
bool reverse_apply = false;
if (auto& obj = config.get("reverse_apply")) {
reverse_apply = obj.get_boolean();
}
if (reverse_apply) {
return dispatch_solver(std::true_type{});
return dispatch<gko::LinOpFactory, IluSolverHelper<true>::Configurator>(
config, context, updated,
make_type_selector(updated.get_value_typestr(), value_type_list()),
make_type_selector(updated.get_index_typestr(), index_type_list()));
} else {
return dispatch_solver(std::false_type{});
return dispatch<gko::LinOpFactory,
IluSolverHelper<false>::Configurator>(
config, context, updated,
make_type_selector(updated.get_value_typestr(), value_type_list()),
make_type_selector(updated.get_index_typestr(), index_type_list()));
}
}

Expand Down
121 changes: 36 additions & 85 deletions core/preconditioner/ilu.cpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
// 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 <ginkgo/core/base/types.hpp>
#include <ginkgo/core/base/utils.hpp>
#include <ginkgo/core/config/config.hpp>
#include <ginkgo/core/config/registry.hpp>
#include <ginkgo/core/config/type_descriptor.hpp>
#include <ginkgo/core/preconditioner/isai.hpp>
#include <ginkgo/core/preconditioner/utils.hpp>
#include <ginkgo/core/solver/gmres.hpp>
#include <ginkgo/core/solver/ir.hpp>

#include "core/config/config_helper.hpp"
#include "core/config/dispatch.hpp"
Expand All @@ -22,24 +19,27 @@ namespace preconditioner {
namespace detail {


template <typename Ilu,
std::enable_if_t<support_ilu_parse<typename Ilu::l_solver_type,
typename Ilu::u_solver_type>>*>
template <typename Ilu, std::enable_if_t<support_ilu_parse<Ilu>>*>
typename Ilu::parameters_type ilu_parse(
const config::pnode& config, const config::registry& context,
const config::type_descriptor& td_for_child)
{
auto params = Ilu::build();

using l_solver_type = typename Ilu::l_solver_type;
using u_solver_type = typename Ilu::u_solver_type;
static_assert(std::is_same_v<l_solver_type, LinOp>,
"only support ILU parse when l_solver_type is LinOp.");
static_assert(std::is_same_v<u_solver_type, LinOp>,
"only support ILU parse when u_solver_type is LinOp.");
if (auto& obj = config.get("l_solver")) {
params.with_l_solver(
gko::config::parse_or_get_specific_factory<
const typename Ilu::l_solver_type>(obj, context, td_for_child));
gko::config::parse_or_get_factory<const LinOpFactory>(
obj, context, td_for_child));
}
if (auto& obj = config.get("u_solver")) {
params.with_u_solver(
gko::config::parse_or_get_specific_factory<
const typename Ilu::u_solver_type>(obj, context, td_for_child));
gko::config::parse_or_get_factory<const LinOpFactory>(
obj, context, td_for_child));
}
if (auto& obj = config.get("factorization")) {
params.with_factorization(
Expand All @@ -51,82 +51,33 @@ typename Ilu::parameters_type ilu_parse(
}


#define GKO_DECLARE_TRS_ILU_FALSE_PARSE(ValueType, IndexType) \
typename Ilu<solver::LowerTrs<ValueType, IndexType>, \
solver::UpperTrs<ValueType, IndexType>, false, \
IndexType>::parameters_type \
ilu_parse<Ilu<solver::LowerTrs<ValueType, IndexType>, \
solver::UpperTrs<ValueType, IndexType>, false, IndexType>>( \
const config::pnode&, const config::registry&, \
const config::type_descriptor&)
GKO_INSTANTIATE_FOR_EACH_VALUE_AND_INDEX_TYPE(GKO_DECLARE_TRS_ILU_FALSE_PARSE);

#define GKO_DECLARE_TRS_ILU_TRUE_PARSE(ValueType, IndexType) \
typename Ilu<solver::LowerTrs<ValueType, IndexType>, \
solver::UpperTrs<ValueType, IndexType>, true, \
IndexType>::parameters_type \
ilu_parse<Ilu<solver::LowerTrs<ValueType, IndexType>, \
solver::UpperTrs<ValueType, IndexType>, true, IndexType>>( \
const config::pnode&, const config::registry&, \
const config::type_descriptor&)
GKO_INSTANTIATE_FOR_EACH_VALUE_AND_INDEX_TYPE(GKO_DECLARE_TRS_ILU_TRUE_PARSE);

#define GKO_DECLARE_GMRES_ILU_FALSE_PARSE(ValueType, IndexType) \
typename Ilu<solver::Gmres<ValueType>, solver::Gmres<ValueType>, false, \
IndexType>::parameters_type \
ilu_parse<Ilu<solver::Gmres<ValueType>, solver::Gmres<ValueType>, false, \
IndexType>>(const config::pnode&, const config::registry&, \
const config::type_descriptor&)
GKO_INSTANTIATE_FOR_EACH_VALUE_AND_INDEX_TYPE(
GKO_DECLARE_GMRES_ILU_FALSE_PARSE);

#define GKO_DECLARE_GMRES_ILU_TRUE_PARSE(ValueType, IndexType) \
typename Ilu<solver::Gmres<ValueType>, solver::Gmres<ValueType>, true, \
IndexType>::parameters_type \
ilu_parse<Ilu<solver::Gmres<ValueType>, solver::Gmres<ValueType>, true, \
IndexType>>(const config::pnode&, const config::registry&, \
const config::type_descriptor&)
GKO_INSTANTIATE_FOR_EACH_VALUE_AND_INDEX_TYPE(GKO_DECLARE_GMRES_ILU_TRUE_PARSE);

#define GKO_DECLARE_IR_ILU_FALSE_PARSE(ValueType, IndexType) \
typename Ilu<solver::Ir<ValueType>, solver::Ir<ValueType>, false, \
IndexType>::parameters_type \
ilu_parse< \
Ilu<solver::Ir<ValueType>, solver::Ir<ValueType>, false, IndexType>>( \
const config::pnode&, const config::registry&, \
const config::type_descriptor&)
GKO_INSTANTIATE_FOR_EACH_VALUE_AND_INDEX_TYPE(GKO_DECLARE_IR_ILU_FALSE_PARSE);

#define GKO_DECLARE_IR_ILU_TRUE_PARSE(ValueType, IndexType) \
typename Ilu<solver::Ir<ValueType>, solver::Ir<ValueType>, true, \
IndexType>::parameters_type \
ilu_parse< \
Ilu<solver::Ir<ValueType>, solver::Ir<ValueType>, true, IndexType>>( \
const config::pnode&, const config::registry&, \
#define GKO_DECLARE_ILU_PARSE_FALSE(ValueType, IndexType) \
typename Ilu<ValueType, ValueType, false, IndexType>::parameters_type \
ilu_parse<Ilu<ValueType, ValueType, false, IndexType>>( \
const config::pnode&, const config::registry&, \
const config::type_descriptor&)
GKO_INSTANTIATE_FOR_EACH_VALUE_AND_INDEX_TYPE(GKO_DECLARE_IR_ILU_TRUE_PARSE);

#define GKO_DECLARE_ISAI_ILU_FALSE_PARSE(ValueType, IndexType) \
typename Ilu<LowerIsai<ValueType, IndexType>, \
UpperIsai<ValueType, IndexType>, false, \
IndexType>::parameters_type \
ilu_parse<Ilu<LowerIsai<ValueType, IndexType>, \
UpperIsai<ValueType, IndexType>, false, IndexType>>( \
const config::pnode&, const config::registry&, \
#define GKO_DECLARE_ILU_PARSE_TRUE(ValueType, IndexType) \
typename Ilu<ValueType, ValueType, true, IndexType>::parameters_type \
ilu_parse<Ilu<ValueType, ValueType, true, IndexType>>( \
const config::pnode&, const config::registry&, \
const config::type_descriptor&)
GKO_INSTANTIATE_FOR_EACH_VALUE_AND_INDEX_TYPE(GKO_DECLARE_ISAI_ILU_FALSE_PARSE);

#define GKO_DECLARE_ISAI_ILU_TRUE_PARSE(ValueType, IndexType) \
typename Ilu<LowerIsai<ValueType, IndexType>, \
UpperIsai<ValueType, IndexType>, true, \
IndexType>::parameters_type \
ilu_parse<Ilu<LowerIsai<ValueType, IndexType>, \
UpperIsai<ValueType, IndexType>, true, IndexType>>( \
const config::pnode&, const config::registry&, \
const config::type_descriptor&)
GKO_INSTANTIATE_FOR_EACH_VALUE_AND_INDEX_TYPE(GKO_DECLARE_ISAI_ILU_TRUE_PARSE);

GKO_INSTANTIATE_FOR_EACH_VALUE_AND_INDEX_TYPE(GKO_DECLARE_ILU_PARSE_FALSE);
GKO_INSTANTIATE_FOR_EACH_VALUE_AND_INDEX_TYPE(GKO_DECLARE_ILU_PARSE_TRUE);


} // namespace detail


// only instantiate the value type variants of ILU, whose solver is LinOp.
#define GKO_DECLARE_ILU_FALSE(ValueType, IndexType) \
class Ilu<ValueType, ValueType, false, IndexType>
#define GKO_DECLARE_ILU_TRUE(ValueType, IndexType) \
class Ilu<ValueType, ValueType, true, IndexType>

GKO_INSTANTIATE_FOR_EACH_VALUE_AND_INDEX_TYPE(GKO_DECLARE_ILU_FALSE);
GKO_INSTANTIATE_FOR_EACH_VALUE_AND_INDEX_TYPE(GKO_DECLARE_ILU_TRUE);


} // namespace preconditioner
} // namespace gko
Loading