Ifpack2 Templated Preconditioning Package  Version 1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
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 
24 namespace Ifpack2 {
25 namespace Details {
26 namespace Impl {
27 
31 template<class DVector,
32  class AMatrix,
33  class DiagOffsetType,
34  bool do_L1,
35  bool fix_tiny>
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 
123 template<class TpetraOperatorType>
126 {
127  setMatrix (A);
128 }
129 
130 template<class TpetraOperatorType>
131 void
132 InverseDiagonalKernel<TpetraOperatorType>::
133 setMatrix (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 
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 
161 template<class TpetraOperatorType>
162 void
163 InverseDiagonalKernel<TpetraOperatorType>::
164 compute (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 =
189  Impl::InverseDiagonalWithExtraction<d_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 =
199  Impl::InverseDiagonalWithExtraction<d_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 =
212  Impl::InverseDiagonalWithExtraction<d_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 =
222  Impl::InverseDiagonalWithExtraction<d_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
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
T * get() const
Compute scaled damped residual for Chebyshev.
Definition: Ifpack2_Details_InverseDiagonalKernel_decl.hpp:45
Functor for extracting the inverse diagonal of a matrix.
Definition: Ifpack2_Details_InverseDiagonalKernel_def.hpp:36
#define TEUCHOS_ASSERT(assertion_test)