MueLu Version of the Day
Loading...
Searching...
No Matches
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
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
24
49template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node, Misc::StrengthMeasure measure>
51 public:
52 using matrix_type = Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>;
53 using diag_vec_type = Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>;
54 using local_matrix_type = typename matrix_type::local_matrix_device_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:
77 Teuchos::RCP<diag_vec_type> diagVec;
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(Tpetra::Access::ReadOnly);
91 diag = Kokkos::subview(lclDiag2d, Kokkos::ALL(), 0);
92 } else if constexpr (measure == Misc::SignedRugeStuebenMeasure) {
94 auto lcl2d = diagVec->getLocalViewDevice(Tpetra::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
167template <Misc::StrengthMeasure measure, class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
168auto make_drop_functor(Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& A_,
171 auto functor = DropFunctor<Scalar, LocalOrdinal, GlobalOrdinal, Node, measure>(A_, threshold, results_);
172 return functor;
173}
174
175} // namespace MueLu::ClassicalDropping
176
177#endif
typename matrix_type::local_matrix_device_type local_matrix_type
DropFunctor(matrix_type &A_, magnitudeType threshold, results_view &results_)
Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > matrix_type
typename local_matrix_type::value_type scalar_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
typename local_matrix_type::memory_space memory_space
typename local_matrix_type::ordinal_type local_ordinal_type
Kokkos::ArithTraits< magnitudeType > mATS
Kokkos::View< const bool *, memory_space > boundary_nodes_view
KOKKOS_FORCEINLINE_FUNCTION void operator()(const local_ordinal_type rlid) const
Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > diag_vec_type
Kokkos::ArithTraits< scalar_type > ATS
static Teuchos::RCP< Vector > GetMatrixMaxMinusOffDiagonal(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A)
Return vector containing: max_{i\not=k}(-a_ik), for each for i in the matrix.
static RCP< Vector > GetMatrixOverlappedDiagonal(const Matrix &A)
Extract Overlapped Matrix Diagonal.
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_)