MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_BoundaryDetection.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_BOUNDARYDETECTION_HPP
11#define MUELU_BOUNDARYDETECTION_HPP
12
13#include <cstddef>
14#include <type_traits>
15#include "Kokkos_Core.hpp"
16#if KOKKOS_VERSION >= 40799
17#include "KokkosKernels_ArithTraits.hpp"
18#else
19#include "Kokkos_ArithTraits.hpp"
20#endif
21#include "MueLu_LWGraph_kokkos.hpp"
22#include "MueLu_Utilities.hpp"
23#include "Teuchos_RCP.hpp"
24#include "Xpetra_ConfigDefs.hpp"
25#include "Xpetra_CrsGraph.hpp"
26#include "Xpetra_MultiVector.hpp"
27
29
37template <class local_matrix_type>
39 private:
40 using scalar_type = typename local_matrix_type::value_type;
41 using local_ordinal_type = typename local_matrix_type::ordinal_type;
42 using memory_space = typename local_matrix_type::memory_space;
43
44#if KOKKOS_VERSION >= 40799
45 using ATS = KokkosKernels::ArithTraits<scalar_type>;
46#else
47 using ATS = Kokkos::ArithTraits<scalar_type>;
48#endif
49 using magnitudeType = typename ATS::magnitudeType;
50 using boundary_nodes_view = Kokkos::View<bool*, memory_space>;
51
52 local_matrix_type A;
56
57 public:
58 PointDirichletFunctor(local_matrix_type& A_, boundary_nodes_view boundaryNodes_, magnitudeType dirichletThreshold_, local_ordinal_type dirichletNonzeroThreshold_)
59 : A(A_)
60 , boundaryNodes(boundaryNodes_)
61 , dirichletThreshold(dirichletThreshold_)
62 , dirichletNonzeroThreshold(dirichletNonzeroThreshold_) {}
63
64 KOKKOS_FORCEINLINE_FUNCTION
65 void operator()(const local_ordinal_type rlid) const {
66 auto row = A.rowConst(rlid);
67 local_ordinal_type nnz = 0;
68 for (local_ordinal_type k = 0; k < row.length; ++k) {
69 local_ordinal_type clid = row.colidx(k);
70 scalar_type val = row.value(k);
71 if ((rlid != static_cast<local_ordinal_type>(clid)) && (ATS::magnitude(val) > dirichletThreshold)) {
72 ++nnz;
73 if (nnz == dirichletNonzeroThreshold) {
74 return;
75 }
76 }
77 }
78 boundaryNodes(rlid) = true;
79 }
80};
81
91template <class local_matrix_type, bool useGreedyDirichlet>
93 private:
94 using scalar_type = typename local_matrix_type::value_type;
95 using local_ordinal_type = typename local_matrix_type::ordinal_type;
96 using memory_space = typename local_matrix_type::memory_space;
97
98#if KOKKOS_VERSION >= 40799
99 using ATS = KokkosKernels::ArithTraits<scalar_type>;
100#else
101 using ATS = Kokkos::ArithTraits<scalar_type>;
102#endif
103 using magnitudeType = typename ATS::magnitudeType;
104 using boundary_nodes_view = Kokkos::View<bool*, memory_space>;
105
106 local_matrix_type A;
111
112 public:
113 VectorDirichletFunctor(local_matrix_type& A_, local_ordinal_type blockSize_, boundary_nodes_view boundaryNodes_, magnitudeType dirichletThreshold_, local_ordinal_type dirichletNonzeroThreshold_)
114 : A(A_)
115 , blockSize(blockSize_)
116 , boundaryNodes(boundaryNodes_)
117 , dirichletThreshold(dirichletThreshold_)
118 , dirichletNonzeroThreshold(dirichletNonzeroThreshold_) {}
119
120 KOKKOS_FORCEINLINE_FUNCTION
121 void operator()(const local_ordinal_type rblid) const {
122 for (local_ordinal_type rlid = rblid * blockSize; rlid < (rblid + 1) * blockSize; ++rlid) {
123 auto row = A.rowConst(rlid);
124 local_ordinal_type nnz = 0;
125 bool rowIsDirichlet = true;
126 for (local_ordinal_type k = 0; k < row.length; ++k) {
127 auto clid = row.colidx(k);
128 auto val = row.value(k);
129 if ((rlid != static_cast<local_ordinal_type>(clid)) && (ATS::magnitude(val) > dirichletThreshold)) {
130 ++nnz;
131 if (nnz == dirichletNonzeroThreshold) {
132 rowIsDirichlet = false;
133 break;
134 }
135 }
136 }
137 if constexpr (useGreedyDirichlet) {
138 if (rowIsDirichlet) {
139 boundaryNodes(rblid) = true;
140 return;
141 }
142 } else {
143 if (!rowIsDirichlet) {
144 return;
145 }
146 }
147 }
148 if constexpr (!useGreedyDirichlet)
149 boundaryNodes(rblid) = true;
150 }
151};
152
160template <class local_matrix_type>
162 private:
163 using scalar_type = typename local_matrix_type::value_type;
164 using local_ordinal_type = typename local_matrix_type::ordinal_type;
165 using memory_space = typename local_matrix_type::memory_space;
166
167#if KOKKOS_VERSION >= 40799
168 using ATS = KokkosKernels::ArithTraits<scalar_type>;
169#else
170 using ATS = Kokkos::ArithTraits<scalar_type>;
171#endif
172 using magnitudeType = typename ATS::magnitudeType;
173#if KOKKOS_VERSION >= 40799
174 using magATS = KokkosKernels::ArithTraits<magnitudeType>;
175#else
176 using magATS = Kokkos::ArithTraits<magnitudeType>;
177#endif
178 using boundary_nodes_view = Kokkos::View<bool*, memory_space>;
179
180 local_matrix_type A;
183
184 public:
185 RowSumFunctor(local_matrix_type& A_, boundary_nodes_view boundaryNodes_, magnitudeType rowSumTol_)
186 : A(A_)
187 , boundaryNodes(boundaryNodes_)
188 , rowSumTol(rowSumTol_) {}
189
190 KOKKOS_FORCEINLINE_FUNCTION
191 void operator()(const local_ordinal_type rlid) const {
192 scalar_type rowsum = ATS::zero();
193 scalar_type diagval = ATS::zero();
194 auto row = A.rowConst(rlid);
195 for (local_ordinal_type k = 0; k < row.length; ++k) {
196 auto clid = row.colidx(k);
197 auto val = row.value(k);
198 if (rlid == static_cast<local_ordinal_type>(clid))
199 diagval = val;
200 rowsum += val;
201 }
202 if (ATS::magnitude(rowsum) > ATS::magnitude(diagval) * rowSumTol) {
203 boundaryNodes(rlid) = true;
204 }
205 }
206};
207
212template <class local_matrix_type, class Functor, class... RemainingFunctors>
214 private:
215 using local_ordinal_type = typename local_matrix_type::ordinal_type;
216
217 Functor functor;
218 BoundaryFunctor<local_matrix_type, RemainingFunctors...> remainingFunctors;
219
220 public:
221 BoundaryFunctor(local_matrix_type& A_, Functor& functor_, RemainingFunctors&... remainingFunctors_)
222 : functor(functor_)
223 , remainingFunctors(A_, remainingFunctors_...) {}
224
225 KOKKOS_FUNCTION void operator()(const local_ordinal_type rlid) const {
226 functor(rlid);
227 remainingFunctors(rlid);
228 }
229};
230
231template <class local_matrix_type, class Functor>
232class BoundaryFunctor<local_matrix_type, Functor> {
233 private:
234 using local_ordinal_type = typename local_matrix_type::ordinal_type;
235
236 local_matrix_type A;
237 Functor functor;
238
239 public:
240 BoundaryFunctor(local_matrix_type& A_, Functor& functor_)
241 : A(A_)
242 , functor(functor_) {}
243
244 KOKKOS_FUNCTION void operator()(const local_ordinal_type rlid) const {
245 functor(rlid);
246 }
247};
248
249} // namespace MueLu::BoundaryDetection
250
251#endif
KOKKOS_FUNCTION void operator()(const local_ordinal_type rlid) const
Functor that serially applies sub-functors to rows.
BoundaryFunctor(local_matrix_type &A_, Functor &functor_, RemainingFunctors &... remainingFunctors_)
BoundaryFunctor< local_matrix_type, RemainingFunctors... > remainingFunctors
typename local_matrix_type::ordinal_type local_ordinal_type
KOKKOS_FUNCTION void operator()(const local_ordinal_type rlid) const
typename local_matrix_type::memory_space memory_space
Kokkos::View< bool *, memory_space > boundary_nodes_view
typename local_matrix_type::ordinal_type local_ordinal_type
KOKKOS_FORCEINLINE_FUNCTION void operator()(const local_ordinal_type rlid) const
PointDirichletFunctor(local_matrix_type &A_, boundary_nodes_view boundaryNodes_, magnitudeType dirichletThreshold_, local_ordinal_type dirichletNonzeroThreshold_)
typename local_matrix_type::value_type scalar_type
Functor for marking nodes as Dirichlet based on rowsum.
RowSumFunctor(local_matrix_type &A_, boundary_nodes_view boundaryNodes_, magnitudeType rowSumTol_)
Kokkos::ArithTraits< magnitudeType > magATS
typename local_matrix_type::value_type scalar_type
typename local_matrix_type::memory_space memory_space
Kokkos::View< bool *, memory_space > boundary_nodes_view
typename local_matrix_type::ordinal_type local_ordinal_type
KOKKOS_FORCEINLINE_FUNCTION void operator()(const local_ordinal_type rlid) const
Functor for marking nodes as Dirichlet in a block operator.
typename local_matrix_type::ordinal_type local_ordinal_type
typename local_matrix_type::memory_space memory_space
Kokkos::View< bool *, memory_space > boundary_nodes_view
typename local_matrix_type::value_type scalar_type
KOKKOS_FORCEINLINE_FUNCTION void operator()(const local_ordinal_type rblid) const
VectorDirichletFunctor(local_matrix_type &A_, local_ordinal_type blockSize_, boundary_nodes_view boundaryNodes_, magnitudeType dirichletThreshold_, local_ordinal_type dirichletNonzeroThreshold_)