Ifpack2 Templated Preconditioning Package Version 1.0
Loading...
Searching...
No Matches
Ifpack2_Details_InverseDiagonalKernel_def.hpp
1// @HEADER
2// *****************************************************************************
3// Ifpack2: Templated Object-Oriented Algebraic Preconditioner Package
4//
5// Copyright 2009 NTESS and the Ifpack2 contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef IFPACK2_DETAILS_INVERSEDIAGONALKERNEL_DEF_HPP
11#define IFPACK2_DETAILS_INVERSEDIAGONALKERNEL_DEF_HPP
12
13#include "Tpetra_CrsMatrix.hpp"
14#include "Tpetra_MultiVector.hpp"
15#include "Tpetra_Operator.hpp"
16#include "Tpetra_Vector.hpp"
17#include "Tpetra_Export_decl.hpp"
18#include "Tpetra_Import_decl.hpp"
19#include "Kokkos_ArithTraits.hpp"
20#include "Teuchos_Assert.hpp"
21#include <type_traits>
22#include "KokkosSparse_spmv_impl.hpp"
23
24namespace Ifpack2 {
25namespace Details {
26namespace Impl {
27
31template<class DVector,
32 class AMatrix,
33 class DiagOffsetType,
34 bool do_L1,
35 bool fix_tiny>
36struct InverseDiagonalWithExtraction {
37
38 using execution_space = typename AMatrix::execution_space;
39 using LO = typename AMatrix::non_const_ordinal_type;
40 using value_type = typename AMatrix::non_const_value_type;
41 using team_policy = typename Kokkos::TeamPolicy<execution_space>;
42 using team_member = typename team_policy::member_type;
43 using ATV = Kokkos::ArithTraits<value_type>;
44 // using IST = typename vector_type::impl_scalar_type;
45 using magnitude_type = typename ATV::mag_type;
46 using MATV = Kokkos::ArithTraits<magnitude_type>;
47
48 DVector m_d;
49 AMatrix m_A;
50 DiagOffsetType m_offsets;
51 magnitude_type m_L1Eta;
52 magnitude_type m_MinDiagonalValue;
53
54 InverseDiagonalWithExtraction (const DVector& m_d_,
55 const AMatrix& m_A_,
56 const DiagOffsetType& m_offsets_,
57 const magnitude_type m_L1Eta_,
58 const magnitude_type m_MinDiagonalValue_) :
59 m_d (m_d_),
60 m_A (m_A_),
61 m_offsets (m_offsets_),
62 m_L1Eta (m_L1Eta_),
63 m_MinDiagonalValue (m_MinDiagonalValue_)
64 {
65 const size_t numRows = m_A.numRows ();
66
67 TEUCHOS_ASSERT( numRows == size_t (m_d.extent (0)) );
68 TEUCHOS_ASSERT( numRows == size_t (m_offsets.extent (0)) );
69 }
70
71 KOKKOS_INLINE_FUNCTION
72 void operator() (const LO lclRow) const
73 {
74 const size_t INV = Tpetra::Details::OrdinalTraits<size_t>::invalid ();
75 const value_type one = ATV::one();
76
77 // In case the row has no entries
78 m_d(lclRow,0) = ATV::zero();
79
80 if (m_offsets(lclRow) != INV) {
81 auto curRow = m_A.rowConst (lclRow);
82 value_type d = curRow.value(m_offsets(lclRow));
83
84 if (do_L1) {
85 // Setup for L1 Methods.
86 // Here we add half the value of the off-processor entries in the row,
87 // but only if diagonal isn't sufficiently large.
88 //
89 // This follows from Equation (6.5) in: Baker, Falgout, Kolev and
90 // Yang. "Multigrid Smoothers for Ultraparallel Computing." SIAM
91 // J. Sci. Comput., Vol. 33, No. 5. (2011), pp. 2864-2887.
92
93 const magnitude_type half = MATV::one () / (MATV::one () + MATV::one ());
94 const LO numRows = static_cast<LO> (m_A.numRows ());
95 const LO row_length = static_cast<LO> (curRow.length);
96 magnitude_type diagonal_boost = MATV::zero();
97 for (LO iEntry = 0; iEntry < row_length; iEntry++) {
98 if (curRow.colidx(iEntry) >= numRows)
99 diagonal_boost += ATV::magnitude(curRow.value(iEntry));
100 }
101 diagonal_boost *= half;
102 if (ATV::magnitude(d) < m_L1Eta * diagonal_boost)
103 d += diagonal_boost;
104 }
105
106 if (fix_tiny) {
107 // Replace diagonal entries that are too small.
108
109 if (ATV::magnitude(d) <= m_MinDiagonalValue)
110 d = m_MinDiagonalValue;
111 }
112
113 // invert diagonal entries
114 m_d(lclRow,0) = one / d;
115 }
116 }
117
118};
119
120} // namespace Impl
121
122
123template<class TpetraOperatorType>
125InverseDiagonalKernel (const Teuchos::RCP<const operator_type>& A)
126{
127 setMatrix (A);
128}
129
130template<class TpetraOperatorType>
131void
132InverseDiagonalKernel<TpetraOperatorType>::
133setMatrix (const Teuchos::RCP<const operator_type>& A)
134{
135 if (A_op_.get () != A.get ()) {
136 A_op_ = A;
137
138 using Teuchos::rcp_dynamic_cast;
139 A_crs_ = rcp_dynamic_cast<const crs_matrix_type> (A);
140
141 TEUCHOS_TEST_FOR_EXCEPTION
142 (A_crs_.is_null(), std::logic_error,
143 "Ifpack2::Details::InverseDiagonalKernel: operator A must be a Tpetra::CrsMatrix.");
144
145 const size_t lclNumRows = A_crs_->getRowMap ()->getLocalNumElements ();
146
147 if (offsets_.extent (0) < lclNumRows) {
148 using Kokkos::view_alloc;
149 using Kokkos::WithoutInitializing;
150 using offsets_view_type = Kokkos::View<size_t*, device_type>;
151
152 offsets_ = offsets_view_type (); // clear 1st to save mem
153 auto howAlloc = view_alloc ("offsets", WithoutInitializing);
154 offsets_ = offsets_view_type (howAlloc, lclNumRows);
155 }
156
157 A_crs_->getCrsGraph ()->getLocalDiagOffsets (offsets_);
158 }
159}
160
161template<class TpetraOperatorType>
162void
164compute (vector_type& D_inv,
165 bool do_l1, magnitude_type L1Eta,
166 bool fixTinyDiagEntries, magnitude_type MinDiagonalValue)
167{
168
169
170 // Canonicalize template arguments to avoid redundant instantiations.
171 using d_type = typename vector_type::dual_view_type::t_dev;
172 // using h_matrix_type = typename crs_matrix_type::local_matrix_host_type;
173 using d_matrix_type = typename crs_matrix_type::local_matrix_device_type;
174
175 const char kernel_label[] = "inverse_diagonal_kernel";
176 using execution_space = typename NT::execution_space;
177 using range_type = Kokkos::RangePolicy<execution_space, LO>;
178 const size_t lclNumRows = A_crs_->getRowMap ()->getLocalNumElements ();
179 auto policy = range_type(0, lclNumRows);
180
181 d_type d = D_inv.getLocalViewDevice(Tpetra::Access::OverwriteAll);
182 d_matrix_type a = A_crs_->getLocalMatrixDevice();
183
184 if (do_l1) {
185 constexpr bool do_l1_template = true;
186 if (fixTinyDiagEntries) {
187 constexpr bool fix_tiny_template = true;
188 using functor_type =
190 d_matrix_type,
191 offset_type,
192 do_l1_template,
193 fix_tiny_template>;
194 functor_type func (d, a, offsets_, L1Eta, MinDiagonalValue);
195 Kokkos::parallel_for (kernel_label, policy, func);
196 } else {
197 constexpr bool fix_tiny_template = false;
198 using functor_type =
200 d_matrix_type,
201 offset_type,
202 do_l1_template,
203 fix_tiny_template>;
204 functor_type func (d, a, offsets_, L1Eta, MinDiagonalValue);
205 Kokkos::parallel_for (kernel_label, policy, func);
206 }
207 } else {
208 constexpr bool do_l1_template = false;
209 if (fixTinyDiagEntries) {
210 constexpr bool fix_tiny_template = true;
211 using functor_type =
213 d_matrix_type,
214 offset_type,
215 do_l1_template,
216 fix_tiny_template>;
217 functor_type func (d, a, offsets_, L1Eta, MinDiagonalValue);
218 Kokkos::parallel_for (kernel_label, policy, func);
219 } else {
220 constexpr bool fix_tiny_template = false;
221 using functor_type =
223 d_matrix_type,
224 offset_type,
225 do_l1_template,
226 fix_tiny_template>;
227 functor_type func (d, a, offsets_, L1Eta, MinDiagonalValue);
228 Kokkos::parallel_for (kernel_label, policy, func);
229 }
230 }
231}
232
233} // namespace Details
234} // namespace Ifpack2
235
236#define IFPACK2_DETAILS_INVERSEDIAGONALKERNEL_INSTANT(SC,LO,GO,NT) \
237 template class Ifpack2::Details::InverseDiagonalKernel<Tpetra::Operator<SC, LO, GO, NT> >;
238
239#endif // IFPACK2_DETAILS_INVERSEDIAGONALKERNEL_DEF_HPP
Compute scaled damped residual for Chebyshev.
Definition Ifpack2_Details_InverseDiagonalKernel_decl.hpp:45
Preconditioners and smoothers for Tpetra sparse matrices.
Definition Ifpack2_AdditiveSchwarz_decl.hpp:41
Functor for extracting the inverse diagonal of a matrix.
Definition Ifpack2_Details_InverseDiagonalKernel_def.hpp:36