5#ifndef GKO_PUBLIC_CORE_PRECONDITIONER_ILU_HPP_
6#define GKO_PUBLIC_CORE_PRECONDITIONER_ILU_HPP_
12#include <ginkgo/core/base/abstract_factory.hpp>
13#include <ginkgo/core/base/composition.hpp>
14#include <ginkgo/core/base/exception.hpp>
15#include <ginkgo/core/base/exception_helpers.hpp>
16#include <ginkgo/core/base/lin_op.hpp>
17#include <ginkgo/core/base/precision_dispatch.hpp>
18#include <ginkgo/core/config/config.hpp>
19#include <ginkgo/core/config/registry.hpp>
20#include <ginkgo/core/factorization/par_ilu.hpp>
21#include <ginkgo/core/matrix/dense.hpp>
22#include <ginkgo/core/preconditioner/isai.hpp>
23#include <ginkgo/core/preconditioner/utils.hpp>
24#include <ginkgo/core/solver/gmres.hpp>
25#include <ginkgo/core/solver/ir.hpp>
26#include <ginkgo/core/solver/solver_traits.hpp>
27#include <ginkgo/core/solver/triangular.hpp>
28#include <ginkgo/core/stop/combined.hpp>
29#include <ginkgo/core/stop/iteration.hpp>
30#include <ginkgo/core/stop/residual_norm.hpp>
38template <
typename LSolverType,
typename USolverType>
39constexpr bool support_ilu_parse =
40 std::is_same<typename USolverType::transposed_type, LSolverType>::value &&
41 (is_instantiation_of<LSolverType, solver::LowerTrs>::value ||
42 is_instantiation_of<LSolverType, solver::Ir>::value ||
43 is_instantiation_of<LSolverType, solver::Gmres>::value ||
44 is_instantiation_of<LSolverType, preconditioner::LowerIsai>::value);
47template <
typename Ilu,
48 std::enable_if_t<!support_ilu_parse<
typename Ilu::l_solver_type,
49 typename Ilu::u_solver_type>>* =
51typename Ilu::parameters_type ilu_parse(
52 const config::pnode& config,
const config::registry& context,
53 const config::type_descriptor& td_for_child)
56 "preconditioner::Ilu only supports limited type for parse.");
61 std::enable_if_t<support_ilu_parse<
typename Ilu::l_solver_type,
62 typename Ilu::u_solver_type>>* =
nullptr>
63typename Ilu::parameters_type ilu_parse(
64 const config::pnode& config,
const config::registry& context,
65 const config::type_descriptor& td_for_child);
119template <
typename LSolverType = solver::LowerTrs<>,
120 typename USolverType = solver::UpperTrs<>,
bool ReverseApply = false,
121 typename IndexType =
int32>
123 Ilu<LSolverType, USolverType, ReverseApply, IndexType>>,
130 std::is_same<
typename LSolverType::value_type,
131 typename USolverType::value_type>::value,
132 "Both the L- and the U-solver must use the same `value_type`!");
133 using value_type =
typename LSolverType::value_type;
134 using l_solver_type = LSolverType;
135 using u_solver_type = USolverType;
136 static constexpr bool performs_reverse_apply = ReverseApply;
137 using index_type = IndexType;
138 using transposed_type =
139 Ilu<
typename USolverType::transposed_type,
140 typename LSolverType::transposed_type, ReverseApply, IndexType>;
149 std::shared_ptr<const typename l_solver_type::Factory>
155 std::shared_ptr<const typename u_solver_type::Factory>
163 GKO_DEPRECATED(
"use with_l_solver instead")
168 return with_l_solver(std::move(
solver));
171 parameters_type& with_l_solver(
175 this->l_solver_generator = std::move(
solver);
176 this->deferred_factories[
"l_solver"] = [](
const auto& exec,
178 if (!params.l_solver_generator.is_empty()) {
179 params.l_solver_factory =
180 params.l_solver_generator.on(exec);
186 GKO_DEPRECATED(
"use with_u_solver instead")
187 parameters_type& with_u_solver_factory(
188 deferred_factory_parameter<const typename u_solver_type::Factory>
191 return with_u_solver(std::move(solver));
194 parameters_type& with_u_solver(
195 deferred_factory_parameter<const typename u_solver_type::Factory>
198 this->u_solver_generator = std::move(solver);
199 this->deferred_factories[
"u_solver"] = [](
const auto& exec,
201 if (!params.u_solver_generator.is_empty()) {
202 params.u_solver_factory =
203 params.u_solver_generator.on(exec);
209 GKO_DEPRECATED(
"use with_factorization instead")
210 parameters_type& with_factorization_factory(
211 deferred_factory_parameter<const LinOpFactory> factorization)
213 return with_factorization(std::move(factorization));
216 parameters_type& with_factorization(
217 deferred_factory_parameter<const LinOpFactory> factorization)
219 this->factorization_generator = std::move(factorization);
220 this->deferred_factories[
"factorization"] = [](
const auto& exec,
222 if (!params.factorization_generator.is_empty()) {
223 params.factorization_factory =
224 params.factorization_generator.on(exec);
231 deferred_factory_parameter<const typename l_solver_type::Factory>
234 deferred_factory_parameter<const typename u_solver_type::Factory>
237 deferred_factory_parameter<const LinOpFactory> factorization_generator;
263 config::make_type_descriptor<value_type, index_type>())
265 return detail::ilu_parse<Ilu>(config, context, td_for_child);
290 std::unique_ptr<transposed_type> transposed{
293 transposed->l_solver_ =
296 transposed->u_solver_ =
300 return std::move(transposed);
305 std::unique_ptr<transposed_type> transposed{
308 transposed->l_solver_ =
311 transposed->u_solver_ =
315 return std::move(transposed);
325 if (&other !=
this) {
328 l_solver_ = other.l_solver_;
329 u_solver_ = other.u_solver_;
330 parameters_ = other.parameters_;
347 if (&other !=
this) {
350 l_solver_ = std::move(other.l_solver_);
351 u_solver_ = std::move(other.u_solver_);
352 parameters_ = std::exchange(other.parameters_, parameters_type{});
353 if (other.get_executor() != exec) {
375 void apply_impl(
const LinOp* b,
LinOp* x)
const override
379 [&](
auto dense_b,
auto dense_x) {
380 this->set_cache_to(dense_b);
382 l_solver_->apply(dense_b, cache_.intermediate);
383 if (u_solver_->apply_uses_initial_guess()) {
384 dense_x->copy_from(cache_.intermediate);
386 u_solver_->apply(cache_.intermediate, dense_x);
388 u_solver_->apply(dense_b, cache_.intermediate);
389 if (l_solver_->apply_uses_initial_guess()) {
390 dense_x->copy_from(cache_.intermediate);
392 l_solver_->apply(cache_.intermediate, dense_x);
399 LinOp* x)
const override
402 [&](
auto dense_alpha,
auto dense_b,
auto dense_beta,
auto dense_x) {
403 this->set_cache_to(dense_b);
405 l_solver_->apply(dense_b, cache_.intermediate);
406 u_solver_->apply(dense_alpha, cache_.intermediate,
407 dense_beta, dense_x);
409 u_solver_->apply(dense_b, cache_.intermediate);
410 l_solver_->apply(dense_alpha, cache_.intermediate,
411 dense_beta, dense_x);
417 explicit Ilu(std::shared_ptr<const Executor> exec)
418 : EnableLinOp<
Ilu>(std::move(exec))
421 explicit Ilu(
const Factory* factory, std::shared_ptr<const LinOp> lin_op)
423 parameters_{
factory->get_parameters()}
426 std::dynamic_pointer_cast<const Composition<value_type>>(lin_op);
427 std::shared_ptr<const LinOp> l_factor;
428 std::shared_ptr<const LinOp> u_factor;
432 auto exec = lin_op->get_executor();
433 if (!parameters_.factorization_factory) {
434 parameters_.factorization_factory =
435 factorization::ParIlu<value_type, index_type>::build().on(
438 auto fact = std::shared_ptr<const LinOp>(
439 parameters_.factorization_factory->generate(lin_op));
442 std::dynamic_pointer_cast<const Composition<value_type>>(fact);
444 GKO_NOT_SUPPORTED(comp);
447 if (comp->get_operators().size() == 2) {
448 l_factor = comp->get_operators()[0];
449 u_factor = comp->get_operators()[1];
451 GKO_NOT_SUPPORTED(comp);
453 GKO_ASSERT_EQUAL_DIMENSIONS(l_factor, u_factor);
458 if (!parameters_.l_solver_factory) {
459 l_solver_ = generate_default_solver<l_solver_type>(exec, l_factor);
461 l_solver_ = parameters_.l_solver_factory->generate(l_factor);
463 if (!parameters_.u_solver_factory) {
464 u_solver_ = generate_default_solver<u_solver_type>(exec, u_factor);
466 u_solver_ = parameters_.u_solver_factory->generate(u_factor);
477 void set_cache_to(
const LinOp* b)
const
479 if (cache_.intermediate ==
nullptr) {
480 cache_.intermediate =
484 cache_.intermediate->copy_from(b);
495 template <
typename SolverType>
496 static std::enable_if_t<solver::has_with_criteria<SolverType>::value,
497 std::unique_ptr<SolverType>>
498 generate_default_solver(
const std::shared_ptr<const Executor>& exec,
499 const std::shared_ptr<const LinOp>& mtx)
503 const unsigned int default_max_iters{
504 static_cast<unsigned int>(mtx->get_size()[0])};
506 return SolverType::build()
508 gko::stop::Iteration::build().with_max_iters(default_max_iters),
509 gko::stop::ResidualNorm<value_type>::build()
510 .with_reduction_factor(default_reduce_residual))
518 template <
typename SolverType>
519 static std::enable_if_t<!solver::has_with_criteria<SolverType>::value,
520 std::unique_ptr<SolverType>>
521 generate_default_solver(
const std::shared_ptr<const Executor>& exec,
522 const std::shared_ptr<const LinOp>& mtx)
524 return SolverType::build().on(exec)->generate(mtx);
528 std::shared_ptr<const l_solver_type> l_solver_{};
529 std::shared_ptr<const u_solver_type> u_solver_{};
540 mutable struct cache_struct {
541 cache_struct() =
default;
542 ~cache_struct() =
default;
543 cache_struct(
const cache_struct&) {}
544 cache_struct(cache_struct&&) {}
545 cache_struct& operator=(
const cache_struct&) {
return *
this; }
546 cache_struct& operator=(cache_struct&&) {
return *
this; }
547 std::unique_ptr<LinOp> intermediate{};
The EnableLinOp mixin can be used to provide sensible default implementations of the majority of the ...
Definition lin_op.hpp:879
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition polymorphic_object.hpp:662
Definition lin_op.hpp:117
LinOp(const LinOp &)=default
Copy-constructs a LinOp.
const dim< 2 > & get_size() const noexcept
Returns the size of the operator.
Definition lin_op.hpp:210
LinOp & operator=(const LinOp &)=default
Copy-assigns a LinOp.
std::shared_ptr< const Executor > get_executor() const noexcept
Returns the Executor of the object.
Definition polymorphic_object.hpp:234
Linear operators which support transposition should implement the Transposable interface.
Definition lin_op.hpp:433
pnode describes a tree of properties.
Definition property_tree.hpp:28
This class stores additional context for creating Ginkgo objects from configuration files.
Definition registry.hpp:167
This class describes the value and index types to be used when building a Ginkgo type from a configur...
Definition type_descriptor.hpp:39
Represents a factory parameter of factory type that can either initialized by a pre-existing factory ...
Definition abstract_factory.hpp:309
The enable_parameters_type mixin is used to create a base implementation of the factory parameters st...
Definition abstract_factory.hpp:211
static std::unique_ptr< Dense > create(std::shared_ptr< const Executor > exec, const dim< 2 > &size={}, size_type stride=0)
Creates an uninitialized Dense matrix of the specified size.
Ilu(Ilu &&other)
Move-constructs an ILU preconditioner.
Definition ilu.hpp:372
Ilu & operator=(Ilu &&other)
Move-assigns an ILU preconditioner.
Definition ilu.hpp:345
std::shared_ptr< const l_solver_type > get_l_solver() const
Returns the solver which is used for the provided L matrix.
Definition ilu.hpp:273
static parameters_type parse(const config::pnode &config, const config::registry &context, const config::type_descriptor &td_for_child=config::make_type_descriptor< value_type, index_type >())
Create the parameters from the property_tree.
Definition ilu.hpp:260
std::unique_ptr< LinOp > conj_transpose() const override
Returns a LinOp representing the conjugate transpose of the Transposable object.
Definition ilu.hpp:303
Ilu(const Ilu &other)
Copy-constructs an ILU preconditioner.
Definition ilu.hpp:365
std::shared_ptr< const u_solver_type > get_u_solver() const
Returns the solver which is used for the provided U matrix.
Definition ilu.hpp:283
std::unique_ptr< LinOp > transpose() const override
Returns a LinOp representing the transpose of the Transposable object.
Definition ilu.hpp:288
Ilu & operator=(const Ilu &other)
Copy-assigns an ILU preconditioner.
Definition ilu.hpp:323
#define GKO_ENABLE_BUILD_METHOD(_factory_name)
Defines a build method for the factory, simplifying its construction by removing the repetitive typin...
Definition abstract_factory.hpp:394
#define GKO_ENABLE_LIN_OP_FACTORY(_lin_op, _parameters_name, _factory_name)
This macro will generate a default implementation of a LinOpFactory for the LinOp subclass it is defi...
Definition lin_op.hpp:1017
@ factory
LinOpFactory events.
Definition profiler_hook.hpp:32
The Preconditioner namespace.
Definition gauss_seidel.hpp:19
The ginkgo Solve namespace.
Definition bicg.hpp:28
The Ginkgo namespace.
Definition abstract_factory.hpp:20
typename detail::remove_complex_s< T >::type remove_complex
Obtain the type which removed the complex of complex/scalar type or the template parameter of class b...
Definition math.hpp:260
void precision_dispatch_real_complex(Function fn, const LinOp *in, LinOp *out)
Calls the given function with the given LinOps temporarily converted to matrix::Dense<ValueType>* as ...
Definition precision_dispatch.hpp:96
detail::cloned_type< Pointer > clone(const Pointer &p)
Creates a unique clone of the object pointed to by p.
Definition utils_helper.hpp:173
batch_dim< 2, DimensionType > transpose(const batch_dim< 2, DimensionType > &input)
Returns a batch_dim object with its dimensions swapped for batched operators.
Definition batch_dim.hpp:119
std::decay_t< T > * as(U *obj)
Performs polymorphic type conversion.
Definition utils_helper.hpp:307
detail::shared_type< OwningPointer > share(OwningPointer &&p)
Marks the object pointed to by p as shared.
Definition utils_helper.hpp:224
std::shared_ptr< const LinOpFactory > factorization_factory
Factory for the factorization.
Definition ilu.hpp:161
std::shared_ptr< const typename u_solver_type::Factory > u_solver_factory
Factory for the U solver.
Definition ilu.hpp:156
std::shared_ptr< const typename l_solver_type::Factory > l_solver_factory
Factory for the L solver.
Definition ilu.hpp:150