MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_ClassicalDropping.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // MueLu: A package for multigrid based preconditioning
4 //
5 // Copyright 2012 NTESS and the MueLu contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef MUELU_CLASSICALDROPPING_HPP
11 #define MUELU_CLASSICALDROPPING_HPP
12 
13 #include "MueLu_DroppingCommon.hpp"
14 #include "Kokkos_Core.hpp"
15 #if KOKKOS_VERSION >= 40799
16 #include "KokkosKernels_ArithTraits.hpp"
17 #else
18 #include "Kokkos_ArithTraits.hpp"
19 #endif
20 #include "Xpetra_Matrix.hpp"
21 #include "MueLu_Utilities.hpp"
22 
23 namespace MueLu::ClassicalDropping {
24 
49 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node, Misc::StrengthMeasure measure>
50 class DropFunctor {
51  public:
54  using local_matrix_type = typename matrix_type::local_matrix_type;
55  using scalar_type = typename local_matrix_type::value_type;
56  using local_ordinal_type = typename local_matrix_type::ordinal_type;
57  using memory_space = typename local_matrix_type::memory_space;
58  using diag_view_type = typename Kokkos::DualView<const scalar_type*, Kokkos::LayoutStride, typename Node::device_type, Kokkos::MemoryUnmanaged>::t_dev;
59 
60  using results_view = Kokkos::View<DecisionType*, memory_space>;
61 
62 #if KOKKOS_VERSION >= 40799
63  using ATS = KokkosKernels::ArithTraits<scalar_type>;
64 #else
65  using ATS = Kokkos::ArithTraits<scalar_type>;
66 #endif
67  using magnitudeType = typename ATS::magnitudeType;
68 #if KOKKOS_VERSION >= 40799
69  using mATS = KokkosKernels::ArithTraits<magnitudeType>;
70 #else
71  using mATS = Kokkos::ArithTraits<magnitudeType>;
72 #endif
73  using boundary_nodes_view = Kokkos::View<const bool*, memory_space>;
74 
75  private:
78  diag_view_type diag; // corresponds to overlapped diagonal
81 
82  public:
84  : A(A_.getLocalMatrixDevice())
85  , eps(threshold)
86  , results(results_) {
87  // Construct ghosted matrix diagonal
88  if constexpr ((measure == Misc::SmoothedAggregationMeasure) || (measure == Misc::SignedSmoothedAggregationMeasure)) {
90  auto lclDiag2d = diagVec->getLocalViewDevice(Xpetra::Access::ReadOnly);
91  diag = Kokkos::subview(lclDiag2d, Kokkos::ALL(), 0);
92  } else if constexpr (measure == Misc::SignedRugeStuebenMeasure) {
94  auto lcl2d = diagVec->getLocalViewDevice(Xpetra::Access::ReadOnly);
95  diag = Kokkos::subview(lcl2d, Kokkos::ALL(), 0);
96  }
97  }
98 
99  KOKKOS_FORCEINLINE_FUNCTION
100  void operator()(const local_ordinal_type rlid) const {
101  auto row = A.rowConst(rlid);
102  size_t offset = A.graph.row_map(rlid);
103 
104 #ifdef MUELU_COALESCE_DROP_DEBUG
105  {
106  Kokkos::printf("SoC: ");
107  for (local_ordinal_type k = 0; k < row.length; ++k) {
108  auto clid = row.colidx(k);
109 
110  auto val = row.value(k);
111 
112  if constexpr (measure == Misc::SmoothedAggregationMeasure) {
113  auto aiiajj = ATS::magnitude(diag(rlid)) * ATS::magnitude(diag(clid)); // |a_ii|*|a_jj|
114  auto aij2 = ATS::magnitude(val) * ATS::magnitude(val); // |a_ij|^2
115 
116  Kokkos::printf("%5f ", ATS::sqrt(aij2 / aiiajj));
117  } else if constexpr (measure == Misc::SignedRugeStuebenMeasure) {
118  auto neg_aij = -ATS::real(val);
119  auto max_neg_aik = eps * ATS::real(diag(rlid));
120 
121  Kokkos::printf("%5f ", neg_aij / max_neg_aik);
122  } else if constexpr (measure == Misc::SignedSmoothedAggregationMeasure) {
123  auto aiiajj = ATS::magnitude(diag(rlid)) * ATS::magnitude(diag(clid)); // |a_ii|*|a_jj|
124  const bool is_nonpositive = ATS::real(val) <= mATS::zero();
125  magnitudeType aij2 = ATS::magnitude(val) * ATS::magnitude(val); // |a_ij|^2
126  // + |a_ij|^2, if a_ij < 0, - |a_ij|^2 if a_ij >=0
127  if (!is_nonpositive)
128  aij2 = -aij2;
129  Kokkos::printf("%5f ", ATS::sqrt(aij2 / aiiajj));
130  }
131  }
132  Kokkos::printf("\n");
133  }
134 #endif
135 
136  for (local_ordinal_type k = 0; k < row.length; ++k) {
137  auto clid = row.colidx(k);
138 
139  auto val = row.value(k);
140 
141  if constexpr (measure == Misc::SmoothedAggregationMeasure) {
142  auto aiiajj = ATS::magnitude(diag(rlid)) * ATS::magnitude(diag(clid)); // |a_ii|*|a_jj|
143  auto aij2 = ATS::magnitude(val) * ATS::magnitude(val); // |a_ij|^2
144 
145  results(offset + k) = Kokkos::max((aij2 <= eps * eps * aiiajj) ? DROP : KEEP,
146  results(offset + k));
147  } else if constexpr (measure == Misc::SignedRugeStuebenMeasure) {
148  auto neg_aij = -ATS::real(val);
149  auto max_neg_aik = eps * ATS::real(diag(rlid));
150  results(offset + k) = Kokkos::max((neg_aij < max_neg_aik) ? DROP : KEEP,
151  results(offset + k));
152  } else if constexpr (measure == Misc::SignedSmoothedAggregationMeasure) {
153  auto aiiajj = ATS::magnitude(diag(rlid)) * ATS::magnitude(diag(clid)); // |a_ii|*|a_jj|
154  const bool is_nonpositive = ATS::real(val) <= mATS::zero();
155  magnitudeType aij2 = ATS::magnitude(val) * ATS::magnitude(val); // |a_ij|^2
156  // + |a_ij|^2, if a_ij < 0, - |a_ij|^2 if a_ij >=0
157  if (!is_nonpositive)
158  aij2 = -aij2;
159  results(offset + k) = Kokkos::max((aij2 <= eps * eps * aiiajj) ? DROP : KEEP,
160  results(offset + k));
161  }
162  }
163  }
164 };
165 
166 // helper function to allow partial template deduction
167 template <Misc::StrengthMeasure measure, class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
171  auto functor = DropFunctor<Scalar, LocalOrdinal, GlobalOrdinal, Node, measure>(A_, threshold, results_);
172  return functor;
173 }
174 
175 } // namespace MueLu::ClassicalDropping
176 
177 #endif
static Teuchos::RCP< Vector > GetMatrixMaxMinusOffDiagonal(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A)
Return vector containing: max_{i=k}(-a_ik), for each for i in the matrix.
Kokkos::View< const bool *, memory_space > boundary_nodes_view
Kokkos::ArithTraits< magnitudeType > mATS
typename local_matrix_type::value_type scalar_type
typename local_matrix_type::memory_space memory_space
DropFunctor(matrix_type &A_, magnitudeType threshold, results_view &results_)
typename matrix_type::local_matrix_type local_matrix_type
Kokkos::View< DecisionType *, memory_space > results_view
typename Kokkos::DualView< const scalar_type *, Kokkos::LayoutStride, typename Node::device_type, Kokkos::MemoryUnmanaged >::t_dev diag_view_type
KOKKOS_FORCEINLINE_FUNCTION void operator()(const local_ordinal_type rlid) const
auto make_drop_functor(Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A_, typename DropFunctor< Scalar, LocalOrdinal, GlobalOrdinal, Node, measure >::magnitudeType threshold, typename DropFunctor< Scalar, LocalOrdinal, GlobalOrdinal, Node, measure >::results_view &results_)
static RCP< Vector > GetMatrixOverlappedDiagonal(const Matrix &A)
Extract Overlapped Matrix Diagonal.
Kokkos::ArithTraits< scalar_type > ATS
typename local_matrix_type::ordinal_type local_ordinal_type