MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_MatrixConstruction.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_MATRIXCONSTRUCTION_HPP
11#define MUELU_MATRIXCONSTRUCTION_HPP
12
13#include "Kokkos_Core.hpp"
14#include "KokkosKernels_ArithTraits.hpp"
15
17
18#include "Xpetra_MatrixFactory.hpp"
19
20#ifdef MUELU_COALESCE_DROP_DEBUG
21// For demangling function names
22#include <cxxabi.h>
23#endif
24
36template <class local_matrix_type, class functor_type, class... remaining_functor_types>
38 private:
39 using scalar_type = typename local_matrix_type::value_type;
40 using local_ordinal_type = typename local_matrix_type::ordinal_type;
41 using memory_space = typename local_matrix_type::memory_space;
42 using results_view = Kokkos::View<DecisionType*, memory_space>;
43
44 using rowptr_type = typename local_matrix_type::row_map_type::non_const_type;
45
46 local_matrix_type A;
49 functor_type functor;
50 PointwiseCountingFunctor<local_matrix_type, remaining_functor_types...> remainingFunctors;
52
53#ifdef MUELU_COALESCE_DROP_DEBUG
54 std::string functorName;
55#endif
56
57 public:
58 PointwiseCountingFunctor(local_matrix_type& A_, results_view& results_, rowptr_type& rowptr_, functor_type& functor_, remaining_functor_types&... remainingFunctors_)
59 : A(A_)
60 , results(results_)
61 , rowptr(rowptr_)
62 , functor(functor_)
63 , remainingFunctors(A_, results_, rowptr_, false, remainingFunctors_...)
64 , firstFunctor(true) {
65#ifdef MUELU_COALESCE_DROP_DEBUG
66 std::string mangledFunctorName = typeid(decltype(functor)).name();
67 int status = 0;
68 char* demangledFunctorName = 0;
69 demangledFunctorName = abi::__cxa_demangle(mangledFunctorName.c_str(), 0, 0, &status);
70 functorName = demangledFunctorName;
71#endif
72 }
73
74 PointwiseCountingFunctor(local_matrix_type& A_, results_view& results_, rowptr_type& rowptr_, bool firstFunctor_, functor_type& functor_, remaining_functor_types&... remainingFunctors_)
75 : A(A_)
76 , results(results_)
77 , rowptr(rowptr_)
78 , functor(functor_)
79 , remainingFunctors(A_, results_, rowptr_, false, remainingFunctors_...)
80 , firstFunctor(firstFunctor_) {
81#ifdef MUELU_COALESCE_DROP_DEBUG
82 std::string mangledFunctorName = typeid(decltype(functor)).name();
83 int status = 0;
84 char* demangledFunctorName = 0;
85 demangledFunctorName = abi::__cxa_demangle(mangledFunctorName.c_str(), 0, 0, &status);
86 functorName = demangledFunctorName;
87#endif
88 }
89
90 KOKKOS_INLINE_FUNCTION
91 void operator()(const local_ordinal_type rlid, local_ordinal_type& nnz, const bool& final) const {
92#ifdef MUELU_COALESCE_DROP_DEBUG
93 if (firstFunctor) {
94 Kokkos::printf("\nStarting on row %d\n", rlid);
95
96 auto row = A.rowConst(rlid);
97
98 Kokkos::printf("indices: ");
99 for (local_ordinal_type k = 0; k < row.length; ++k) {
100 auto clid = row.colidx(k);
101 Kokkos::printf("%5d ", clid);
102 }
103 Kokkos::printf("\n");
104
105 Kokkos::printf("values: ");
106 for (local_ordinal_type k = 0; k < row.length; ++k) {
107 auto val = row.value(k);
108 Kokkos::printf("%5f ", val);
109 }
110 Kokkos::printf("\n");
111 }
112#endif
113
114 functor(rlid);
115
116#ifdef MUELU_COALESCE_DROP_DEBUG
117 {
118 Kokkos::printf("%s\n", functorName.c_str());
119
120 auto row = A.rowConst(rlid);
121 const size_t offset = A.graph.row_map(rlid);
122
123 Kokkos::printf("decisions: ");
124 for (local_ordinal_type k = 0; k < row.length; ++k) {
125 Kokkos::printf("%5d ", results(offset + k));
126 }
127 Kokkos::printf("\n");
128 }
129#endif
130
131 remainingFunctors(rlid, nnz, final);
132 }
133};
134
135template <class local_matrix_type, class functor_type>
136class PointwiseCountingFunctor<local_matrix_type, functor_type> {
137 private:
138 using scalar_type = typename local_matrix_type::value_type;
139 using local_ordinal_type = typename local_matrix_type::ordinal_type;
140 using memory_space = typename local_matrix_type::memory_space;
141 using results_view = Kokkos::View<DecisionType*, memory_space>;
142
143 using rowptr_type = typename local_matrix_type::row_map_type::non_const_type;
144
145 local_matrix_type A;
148 functor_type functor;
150
151#ifdef MUELU_COALESCE_DROP_DEBUG
152 std::string functorName;
153#endif
154
155 public:
156 PointwiseCountingFunctor(local_matrix_type& A_, results_view& results_, rowptr_type& rowptr_, functor_type& functor_)
157 : A(A_)
158 , results(results_)
159 , rowptr(rowptr_)
160 , functor(functor_)
161 , firstFunctor(true) {
162#ifdef MUELU_COALESCE_DROP_DEBUG
163 std::string mangledFunctorName = typeid(decltype(functor)).name();
164 int status = 0;
165 char* demangledFunctorName = 0;
166 demangledFunctorName = abi::__cxa_demangle(mangledFunctorName.c_str(), 0, 0, &status);
167 functorName = demangledFunctorName;
168#endif
169 }
170
171 PointwiseCountingFunctor(local_matrix_type& A_, results_view& results_, rowptr_type& rowptr_, bool firstFunctor_, functor_type& functor_)
172 : A(A_)
173 , results(results_)
174 , rowptr(rowptr_)
175 , functor(functor_)
176 , firstFunctor(firstFunctor_) {
177#ifdef MUELU_COALESCE_DROP_DEBUG
178 std::string mangledFunctorName = typeid(decltype(functor)).name();
179 int status = 0;
180 char* demangledFunctorName = 0;
181 demangledFunctorName = abi::__cxa_demangle(mangledFunctorName.c_str(), 0, 0, &status);
182 functorName = demangledFunctorName;
183#endif
184 }
185
186 KOKKOS_INLINE_FUNCTION
187 void operator()(const local_ordinal_type rlid, local_ordinal_type& nnz, const bool& final) const {
188#ifdef MUELU_COALESCE_DROP_DEBUG
189 if (firstFunctor) {
190 Kokkos::printf("\nStarting on row %d\n", rlid);
191
192 auto row = A.rowConst(rlid);
193
194 Kokkos::printf("indices: ");
195 for (local_ordinal_type k = 0; k < row.length; ++k) {
196 auto clid = row.colidx(k);
197 Kokkos::printf("%5d ", clid);
198 }
199 Kokkos::printf("\n");
200
201 Kokkos::printf("values: ");
202 for (local_ordinal_type k = 0; k < row.length; ++k) {
203 auto val = row.value(k);
204 Kokkos::printf("%5f ", val);
205 }
206 Kokkos::printf("\n");
207 }
208#endif
209
210 functor(rlid);
211
212#ifdef MUELU_COALESCE_DROP_DEBUG
213 Kokkos::printf("%s\n", functorName.c_str());
214
215 auto row = A.rowConst(rlid);
216 const size_t offset = A.graph.row_map(rlid);
217
218 Kokkos::printf("decisions: ");
219 for (local_ordinal_type k = 0; k < row.length; ++k) {
220 Kokkos::printf("%5d ", results(offset + k));
221 }
222
223 Kokkos::printf("\n");
224 Kokkos::printf("Done with row %d\n", rlid);
225#endif
226
227 size_t start = A.graph.row_map(rlid);
228 size_t end = A.graph.row_map(rlid + 1);
229 for (size_t i = start; i < end; ++i) {
230 if (results(i) == KEEP) {
231 ++nnz;
232 }
233 }
234 if (final)
235 rowptr(rlid + 1) = nnz;
236 }
237};
238
247template <class local_matrix_type, class local_graph_type, bool lumping>
249 private:
250 using scalar_type = typename local_matrix_type::value_type;
251 using local_ordinal_type = typename local_matrix_type::ordinal_type;
252 using memory_space = typename local_matrix_type::memory_space;
253 using results_view = Kokkos::View<DecisionType*, memory_space>;
254 using ATS = KokkosKernels::ArithTraits<scalar_type>;
255 using magnitudeType = typename ATS::magnitudeType;
256
257 local_matrix_type A;
259 local_matrix_type filteredA;
260 local_graph_type graph;
262 const scalar_type zero = ATS::zero();
263 const scalar_type one = ATS::one();
264
265 public:
266 PointwiseFillReuseFunctor(local_matrix_type& A_, results_view& results_, local_matrix_type& filteredA_, local_graph_type& graph_, magnitudeType dirichletThreshold_)
267 : A(A_)
268 , results(results_)
269 , filteredA(filteredA_)
270 , graph(graph_)
271 , dirichletThreshold(dirichletThreshold_) {}
272
273 KOKKOS_INLINE_FUNCTION
274 void operator()(const local_ordinal_type rlid) const {
275 auto rowA = A.row(rlid);
276 size_t row_start = A.graph.row_map(rlid);
277 auto rowFilteredA = filteredA.row(rlid);
278 local_ordinal_type j = 0;
279 local_ordinal_type jj = 0;
280 local_ordinal_type graph_offset = graph.row_map(rlid);
281 scalar_type diagCorrection = zero;
282 local_ordinal_type diagOffset = -1;
283 for (local_ordinal_type k = 0; k < rowA.length; ++k) {
284 if constexpr (lumping) {
285 local_ordinal_type clid = rowA.colidx(k);
286 if (rlid == clid) {
287 diagOffset = j;
288 }
289 }
290 if (results(row_start + k) == KEEP) {
291 rowFilteredA.colidx(j) = rowA.colidx(k);
292 rowFilteredA.value(j) = rowA.value(k);
293 ++j;
294 graph.entries(graph_offset + jj) = rowA.colidx(k);
295 ++jj;
296 } else if constexpr (lumping) {
297 diagCorrection += rowA.value(k);
298 rowFilteredA.colidx(j) = rowA.colidx(k);
299 rowFilteredA.value(j) = zero;
300 ++j;
301 } else {
302 rowFilteredA.colidx(j) = rowA.colidx(k);
303 rowFilteredA.value(j) = zero;
304 ++j;
305 }
306 }
307 if constexpr (lumping) {
308 rowFilteredA.value(diagOffset) += diagCorrection;
309 if ((dirichletThreshold >= 0.0) && (ATS::real(rowFilteredA.value(diagOffset)) <= dirichletThreshold))
310 rowFilteredA.value(diagOffset) = one;
311 }
312 }
313};
317
326template <class local_matrix_type, lumpingType lumpingChoice>
328 private:
329 using scalar_type = typename local_matrix_type::value_type;
330 using local_ordinal_type = typename local_matrix_type::ordinal_type;
331 using memory_space = typename local_matrix_type::memory_space;
332 using results_view = Kokkos::View<DecisionType*, memory_space>;
333 using ATS = KokkosKernels::ArithTraits<scalar_type>;
334 using magnitudeType = typename ATS::magnitudeType;
335
336 local_matrix_type A;
338 local_matrix_type filteredA;
340 const scalar_type zero = ATS::zero();
341 const scalar_type one = ATS::one();
342
343 public:
344 PointwiseFillNoReuseFunctor(local_matrix_type& A_, results_view& results_, local_matrix_type& filteredA_, magnitudeType dirichletThreshold_)
345 : A(A_)
346 , results(results_)
347 , filteredA(filteredA_)
348 , dirichletThreshold(dirichletThreshold_) {}
349
350 KOKKOS_INLINE_FUNCTION
351 void operator()(const local_ordinal_type rlid) const {
352 auto rowA = A.row(rlid);
353 size_t K = A.graph.row_map(rlid);
354 auto rowFilteredA = filteredA.row(rlid);
355 local_ordinal_type j = 0;
356 scalar_type droppedSum = zero;
357 scalar_type keptRowSumAbs = zero;
358 local_ordinal_type diagOffset = -1;
359 for (local_ordinal_type k = 0; k < rowA.length; ++k) {
360 if constexpr (lumpingChoice != no_lumping) {
361 local_ordinal_type clid = rowA.colidx(k);
362 if (rlid == clid) {
363 diagOffset = j;
364 }
365 }
366 if (results(K + k) == KEEP) {
367 rowFilteredA.colidx(j) = rowA.colidx(k);
368 rowFilteredA.value(j) = rowA.value(k);
369 if constexpr (lumpingChoice == distributed_lumping) {
370 keptRowSumAbs += ATS::magnitude(rowFilteredA.value(j));
371 }
372 ++j;
373 } else if constexpr (lumpingChoice != no_lumping) {
374 droppedSum += rowA.value(k);
375 }
376 }
377 if constexpr (lumpingChoice == diag_lumping) {
378 rowFilteredA.value(diagOffset) += droppedSum;
379 if ((dirichletThreshold >= 0.0) && (ATS::real(rowFilteredA.value(diagOffset)) <= dirichletThreshold))
380 rowFilteredA.value(diagOffset) = one;
381 } else if constexpr (lumpingChoice == distributed_lumping) {
382 if (ATS::real(droppedSum) >= ATS::real(zero)) {
383 rowFilteredA.value(diagOffset) += droppedSum;
384
385 } else {
386 for (local_ordinal_type k = 0; k < j; ++k) {
387 rowFilteredA.value(k) += droppedSum * ATS::magnitude(rowFilteredA.value(k)) / keptRowSumAbs;
388 }
389 }
390 }
391 }
392};
393
394template <class local_matrix_type>
396 public:
397 using local_ordinal_type = typename local_matrix_type::ordinal_type;
398 using memory_space = typename local_matrix_type::memory_space;
399 using block_indices_view_type = Kokkos::View<local_ordinal_type*, memory_space>;
400
401 local_matrix_type A;
404
405 public:
406 BlockRowComparison(local_matrix_type& A_, local_ordinal_type bsize_, block_indices_view_type ghosted_point_to_block_)
407 : A(A_)
408 , bsize(bsize_)
409 , ghosted_point_to_block(ghosted_point_to_block_) {}
410
411 template <class local_matrix_type2>
412 struct Comparator {
413 private:
414 using local_ordinal_type = typename local_matrix_type2::ordinal_type;
415 using memory_space = typename local_matrix_type2::memory_space;
416 using block_indices_view_type = Kokkos::View<local_ordinal_type*, memory_space>;
417
418 const local_matrix_type2 A;
421
422 public:
423 KOKKOS_INLINE_FUNCTION
424 Comparator(const local_matrix_type2& A_, local_ordinal_type bsize_, local_ordinal_type brlid_, block_indices_view_type ghosted_point_to_block_)
425 : A(A_)
426 , offset(A_.graph.row_map(bsize_ * brlid_))
427 , ghosted_point_to_block(ghosted_point_to_block_) {}
428
429 KOKKOS_INLINE_FUNCTION
430 bool operator()(size_t x, size_t y) const {
431 return ghosted_point_to_block(A.graph.entries(offset + x)) < ghosted_point_to_block(A.graph.entries(offset + y));
432 }
433 };
434
436
437 KOKKOS_INLINE_FUNCTION
441};
442
453template <class local_matrix_type,
454 class functor_type,
455 class... remaining_functor_types>
457 private:
458 using scalar_type = typename local_matrix_type::value_type;
459 using local_ordinal_type = typename local_matrix_type::ordinal_type;
460 using memory_space = typename local_matrix_type::memory_space;
461 using results_view = Kokkos::View<DecisionType*, memory_space>;
462 using block_indices_view_type = Kokkos::View<local_ordinal_type*, memory_space>;
463 using permutation_type = Kokkos::View<local_ordinal_type*, memory_space>;
464
465 using rowptr_type = typename local_matrix_type::row_map_type::non_const_type;
466 using ATS = KokkosKernels::ArithTraits<local_ordinal_type>;
467
468 local_matrix_type A;
474
475 functor_type functor;
476
479
480 VectorCountingFunctor<local_matrix_type, remaining_functor_types...> remainingFunctors;
481
482#ifdef MUELU_COALESCE_DROP_DEBUG
483 std::string functorName;
484#endif
485
486 public:
487 VectorCountingFunctor(local_matrix_type& A_, local_ordinal_type blockSize_, block_indices_view_type ghosted_point_to_block_, results_view& results_, rowptr_type& filtered_rowptr_, rowptr_type& graph_rowptr_, functor_type& functor_, remaining_functor_types&... remainingFunctors_)
488 : A(A_)
489 , blockSize(blockSize_)
490 , ghosted_point_to_block(ghosted_point_to_block_)
491 , results(results_)
492 , filtered_rowptr(filtered_rowptr_)
493 , graph_rowptr(graph_rowptr_)
494 , functor(functor_)
496 , remainingFunctors(A_, blockSize_, ghosted_point_to_block_, results_, filtered_rowptr_, graph_rowptr_, remainingFunctors_...) {
497 permutation = permutation_type("permutation", A.nnz());
498#ifdef MUELU_COALESCE_DROP_DEBUG
499 std::string mangledFunctorName = typeid(decltype(functor)).name();
500 int status = 0;
501 char* demangledFunctorName = 0;
502 demangledFunctorName = abi::__cxa_demangle(mangledFunctorName.c_str(), 0, 0, &status);
503 functorName = demangledFunctorName;
504#endif
505 }
506
507 KOKKOS_INLINE_FUNCTION
508 void join(Kokkos::pair<local_ordinal_type, local_ordinal_type>& dest, const Kokkos::pair<local_ordinal_type, local_ordinal_type>& src) const {
509 dest.first += src.first;
510 dest.second += src.second;
511 }
512
513 KOKKOS_INLINE_FUNCTION
514 void operatorRow(const local_ordinal_type rlid) const {
515 functor(rlid);
516 remainingFunctors.operatorRow(rlid);
517 }
518
519 KOKKOS_INLINE_FUNCTION
520 void operator()(const local_ordinal_type brlid, Kokkos::pair<local_ordinal_type, local_ordinal_type>& nnz, const bool& final) const {
521 auto nnz_filtered = &nnz.first;
522 auto nnz_graph = &nnz.second;
523
524#ifdef MUELU_COALESCE_DROP_DEBUG
525 Kokkos::printf("\nStarting on block row %d\n", brlid);
526#endif
527 for (local_ordinal_type rlid = blockSize * brlid; rlid < blockSize * (brlid + 1); ++rlid) {
528#ifdef MUELU_COALESCE_DROP_DEBUG
529 {
530 Kokkos::printf("\nStarting on row %d\n", rlid);
531
532 auto row = A.rowConst(rlid);
533
534 Kokkos::printf("indices: ");
535 for (local_ordinal_type k = 0; k < row.length; ++k) {
536 auto clid = row.colidx(k);
537 Kokkos::printf("%5d ", clid);
538 }
539 Kokkos::printf("\n");
540
541 Kokkos::printf("values: ");
542 for (local_ordinal_type k = 0; k < row.length; ++k) {
543 auto val = row.value(k);
544 Kokkos::printf("%5f ", val);
545 }
546 Kokkos::printf("\n");
547 }
548#endif
549
550 functor(rlid);
551 remainingFunctors.operatorRow(rlid);
552
553#ifdef MUELU_COALESCE_DROP_DEBUG
554 {
555 Kokkos::printf("%s\n", functorName.c_str());
556
557 auto row = A.rowConst(rlid);
558 const size_t offset = A.graph.row_map(rlid);
559
560 Kokkos::printf("decisions: ");
561 for (local_ordinal_type k = 0; k < row.length; ++k) {
562 Kokkos::printf("%5d ", results(offset + k));
563 }
564 Kokkos::printf("\n");
565 }
566#endif
567
568#ifdef MUELU_COALESCE_DROP_DEBUG
569 Kokkos::printf("Done with row %d\n", rlid);
570#endif
571
572 size_t start = A.graph.row_map(rlid);
573 size_t end = A.graph.row_map(rlid + 1);
574 for (size_t i = start; i < end; ++i) {
575 if (results(i) == KEEP) {
576 ++(*nnz_filtered);
577 }
578 }
579 if (final)
580 filtered_rowptr(rlid + 1) = *nnz_filtered;
581 }
582
583#ifdef MUELU_COALESCE_DROP_DEBUG
584 Kokkos::printf("Done with block row %d\nGraph indices ", brlid);
585#endif
586
587 // column lids for all rows in the block
588 auto block_clids = Kokkos::subview(A.graph.entries, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
589 A.graph.row_map(blockSize * (brlid + 1))));
590 // set up a permutatation index
591 auto block_permutation = Kokkos::subview(permutation, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
592 A.graph.row_map(blockSize * (brlid + 1))));
593 for (size_t i = 0; i < block_permutation.extent(0); ++i)
594 block_permutation(i) = i;
595 // get permuatation for sorted column indices of the entire block
596 auto comparator = comparison.getComparator(brlid);
597 Misc::serialHeapSort(block_permutation, comparator);
598
599 local_ordinal_type prev_bclid = -1;
600 bool alreadyAdded = false;
601
602 // loop over all sorted entries in block
603 auto offset = A.graph.row_map(blockSize * brlid);
604 for (size_t i = 0; i < block_permutation.extent(0); ++i) {
605 auto idx = offset + block_permutation(i);
606 auto clid = A.graph.entries(idx);
607 auto bclid = ghosted_point_to_block(clid);
608
609 // unseen block column index
610 if (bclid > prev_bclid)
611 alreadyAdded = false;
612
613 // add entry to graph
614 if (!alreadyAdded && (results(idx) == KEEP)) {
615 ++(*nnz_graph);
616 alreadyAdded = true;
617#ifdef MUELU_COALESCE_DROP_DEBUG
618 Kokkos::printf("%5d ", bclid);
619#endif
620 }
621 prev_bclid = bclid;
622 }
623#ifdef MUELU_COALESCE_DROP_DEBUG
624 Kokkos::printf("\n");
625#endif
626 if (final)
627 graph_rowptr(brlid + 1) = *nnz_graph;
628 }
629};
630
631template <class local_matrix_type,
632 class functor_type>
633class VectorCountingFunctor<local_matrix_type, functor_type> {
634 private:
635 using scalar_type = typename local_matrix_type::value_type;
636 using local_ordinal_type = typename local_matrix_type::ordinal_type;
637 using memory_space = typename local_matrix_type::memory_space;
638 using results_view = Kokkos::View<DecisionType*, memory_space>;
639 using block_indices_view_type = Kokkos::View<local_ordinal_type*, memory_space>;
640 using permutation_type = Kokkos::View<local_ordinal_type*, memory_space>;
641
642 using rowptr_type = typename local_matrix_type::row_map_type::non_const_type;
643 using ATS = KokkosKernels::ArithTraits<local_ordinal_type>;
644
645 local_matrix_type A;
651
652 functor_type functor;
653
654#ifdef MUELU_COALESCE_DROP_DEBUG
655 std::string functorName;
656#endif
657
660
661 public:
662 VectorCountingFunctor(local_matrix_type& A_, local_ordinal_type blockSize_, block_indices_view_type ghosted_point_to_block_, results_view& results_, rowptr_type& filtered_rowptr_, rowptr_type& graph_rowptr_, functor_type& functor_)
663 : A(A_)
664 , blockSize(blockSize_)
665 , ghosted_point_to_block(ghosted_point_to_block_)
666 , results(results_)
667 , filtered_rowptr(filtered_rowptr_)
668 , graph_rowptr(graph_rowptr_)
669 , functor(functor_)
671 permutation = permutation_type("permutation", A.nnz());
672#ifdef MUELU_COALESCE_DROP_DEBUG
673 std::string mangledFunctorName = typeid(decltype(functor)).name();
674 int status = 0;
675 char* demangledFunctorName = 0;
676 demangledFunctorName = abi::__cxa_demangle(mangledFunctorName.c_str(), 0, 0, &status);
677 functorName = demangledFunctorName;
678#endif
679 }
680
681 KOKKOS_INLINE_FUNCTION
682 void join(Kokkos::pair<local_ordinal_type, local_ordinal_type>& dest, const Kokkos::pair<local_ordinal_type, local_ordinal_type>& src) const {
683 dest.first += src.first;
684 dest.second += src.second;
685 }
686
687 KOKKOS_INLINE_FUNCTION
688 void operatorRow(const local_ordinal_type rlid) const {
689 functor(rlid);
690 }
691
692 KOKKOS_INLINE_FUNCTION
693 void operator()(const local_ordinal_type brlid, Kokkos::pair<local_ordinal_type, local_ordinal_type>& nnz, const bool& final) const {
694 auto nnz_filtered = &nnz.first;
695 auto nnz_graph = &nnz.second;
696
697#ifdef MUELU_COALESCE_DROP_DEBUG
698 Kokkos::printf("\nStarting on block row %d\n", brlid);
699#endif
700 for (local_ordinal_type rlid = blockSize * brlid; rlid < blockSize * (brlid + 1); ++rlid) {
701#ifdef MUELU_COALESCE_DROP_DEBUG
702 {
703 Kokkos::printf("\nStarting on row %d\n", rlid);
704
705 auto row = A.rowConst(rlid);
706
707 Kokkos::printf("indices: ");
708 for (local_ordinal_type k = 0; k < row.length; ++k) {
709 auto clid = row.colidx(k);
710 Kokkos::printf("%5d ", clid);
711 }
712 Kokkos::printf("\n");
713
714 Kokkos::printf("values: ");
715 for (local_ordinal_type k = 0; k < row.length; ++k) {
716 auto val = row.value(k);
717 Kokkos::printf("%5f ", val);
718 }
719 Kokkos::printf("\n");
720 }
721#endif
722
723 functor(rlid);
724
725#ifdef MUELU_COALESCE_DROP_DEBUG
726 {
727 Kokkos::printf("%s\n", functorName.c_str());
728
729 auto row = A.rowConst(rlid);
730 const size_t offset = A.graph.row_map(rlid);
731
732 Kokkos::printf("decisions: ");
733 for (local_ordinal_type k = 0; k < row.length; ++k) {
734 Kokkos::printf("%5d ", results(offset + k));
735 }
736 Kokkos::printf("\n");
737 }
738#endif
739
740#ifdef MUELU_COALESCE_DROP_DEBUG
741 Kokkos::printf("Done with row %d\n", rlid);
742#endif
743
744 size_t start = A.graph.row_map(rlid);
745 size_t end = A.graph.row_map(rlid + 1);
746 for (size_t i = start; i < end; ++i) {
747 if (results(i) == KEEP) {
748 ++(*nnz_filtered);
749 }
750 }
751 if (final)
752 filtered_rowptr(rlid + 1) = *nnz_filtered;
753 }
754
755#ifdef MUELU_COALESCE_DROP_DEBUG
756 Kokkos::printf("Done with block row %d\nGraph indices ", brlid);
757#endif
758
759 // column lids for all rows in the block
760 auto block_clids = Kokkos::subview(A.graph.entries, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
761 A.graph.row_map(blockSize * (brlid + 1))));
762 // set up a permutation index
763 auto block_permutation = Kokkos::subview(permutation, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
764 A.graph.row_map(blockSize * (brlid + 1))));
765 for (size_t i = 0; i < block_permutation.extent(0); ++i)
766 block_permutation(i) = i;
767 // get permutation for sorted column indices of the entire block
768 auto comparator = comparison.getComparator(brlid);
769 Misc::serialHeapSort(block_permutation, comparator);
770
771 local_ordinal_type prev_bclid = -1;
772 bool alreadyAdded = false;
773
774 // loop over all sorted entries in block
775 auto offset = A.graph.row_map(blockSize * brlid);
776 for (size_t i = 0; i < block_permutation.extent(0); ++i) {
777 auto idx = offset + block_permutation(i);
778 auto clid = A.graph.entries(idx);
779 auto bclid = ghosted_point_to_block(clid);
780
781 // unseen block column index
782 if (bclid > prev_bclid)
783 alreadyAdded = false;
784
785 // add entry to graph
786 if (!alreadyAdded && (results(idx) == KEEP)) {
787 ++(*nnz_graph);
788 alreadyAdded = true;
789#ifdef MUELU_COALESCE_DROP_DEBUG
790 Kokkos::printf("%5d ", bclid);
791#endif
792 }
793 prev_bclid = bclid;
794 }
795#ifdef MUELU_COALESCE_DROP_DEBUG
796 Kokkos::printf("\n");
797#endif
798 if (final)
799 graph_rowptr(brlid + 1) = *nnz_graph;
800 }
801};
802
810template <class local_matrix_type, bool lumping, bool reuse>
812 private:
813 using scalar_type = typename local_matrix_type::value_type;
814 using local_ordinal_type = typename local_matrix_type::ordinal_type;
815 using local_graph_type = typename local_matrix_type::staticcrsgraph_type;
816 using memory_space = typename local_matrix_type::memory_space;
817 using results_view = Kokkos::View<DecisionType*, memory_space>;
818 using ATS = KokkosKernels::ArithTraits<scalar_type>;
819 using OTS = KokkosKernels::ArithTraits<local_ordinal_type>;
820 using block_indices_view_type = Kokkos::View<local_ordinal_type*, memory_space>;
821 using permutation_type = Kokkos::View<local_ordinal_type*, memory_space>;
822 using magnitudeType = typename ATS::magnitudeType;
823
824 local_matrix_type A;
828 local_matrix_type filteredA;
831 const scalar_type zero = ATS::zero();
832 const scalar_type one = ATS::one();
833
836
837 public:
838 VectorFillFunctor(local_matrix_type& A_, local_ordinal_type blockSize_, block_indices_view_type ghosted_point_to_block_, results_view& results_, local_matrix_type& filteredA_, local_graph_type& graph_, magnitudeType dirichletThreshold_)
839 : A(A_)
840 , blockSize(blockSize_)
841 , ghosted_point_to_block(ghosted_point_to_block_)
842 , results(results_)
843 , filteredA(filteredA_)
844 , graph(graph_)
845 , dirichletThreshold(dirichletThreshold_)
847 permutation = permutation_type("permutation", A.nnz());
848 }
849
850 KOKKOS_INLINE_FUNCTION
851 void operator()(const local_ordinal_type brlid) const {
852 for (local_ordinal_type rlid = blockSize * brlid; rlid < blockSize * (brlid + 1); ++rlid) {
853 auto rowA = A.row(rlid);
854 size_t row_start = A.graph.row_map(rlid);
855 auto rowFilteredA = filteredA.row(rlid);
856 local_ordinal_type j = 0;
857 scalar_type diagCorrection = zero;
858 local_ordinal_type diagOffset = -1;
859 for (local_ordinal_type k = 0; k < rowA.length; ++k) {
860 if constexpr (lumping) {
861 local_ordinal_type clid = rowA.colidx(k);
862 if (rlid == clid) {
863 diagOffset = j;
864 }
865 }
866 if (results(row_start + k) == KEEP) {
867 rowFilteredA.colidx(j) = rowA.colidx(k);
868 rowFilteredA.value(j) = rowA.value(k);
869 ++j;
870 } else if constexpr (lumping) {
871 diagCorrection += rowA.value(k);
872 if constexpr (reuse) {
873 rowFilteredA.colidx(j) = rowA.colidx(k);
874 rowFilteredA.value(j) = zero;
875 ++j;
876 }
877 } else if constexpr (reuse) {
878 rowFilteredA.colidx(j) = rowA.colidx(k);
879 rowFilteredA.value(j) = zero;
880 ++j;
881 }
882 }
883 if constexpr (lumping) {
884 rowFilteredA.value(diagOffset) += diagCorrection;
885 if ((dirichletThreshold >= 0.0) && (ATS::real(rowFilteredA.value(diagOffset)) <= dirichletThreshold))
886 rowFilteredA.value(diagOffset) = one;
887 }
888 }
889
890 // column lids for all rows in the block
891 auto block_clids = Kokkos::subview(A.graph.entries, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
892 A.graph.row_map(blockSize * (brlid + 1))));
893 // set up a permuatation index
894 auto block_permutation = Kokkos::subview(permutation, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
895 A.graph.row_map(blockSize * (brlid + 1))));
896 for (size_t i = 0; i < block_permutation.extent(0); ++i)
897 block_permutation(i) = i;
898 // get permutation for sorted column indices of the entire block
899 auto comparator = comparison.getComparator(brlid);
900 Misc::serialHeapSort(block_permutation, comparator);
901
902 local_ordinal_type prev_bclid = -1;
903 bool alreadyAdded = false;
904 local_ordinal_type j = graph.row_map(brlid);
905
906 // loop over all sorted entries in block
907 auto offset = A.graph.row_map(blockSize * brlid);
908 for (size_t i = 0; i < block_permutation.extent(0); ++i) {
909 auto idx = offset + block_permutation(i);
910 auto clid = A.graph.entries(idx);
911 auto bclid = ghosted_point_to_block(clid);
912
913 // unseen block column index
914 if (bclid > prev_bclid)
915 alreadyAdded = false;
916
917 // add entry to graph
918 if (!alreadyAdded && (results(idx) == KEEP)) {
919 graph.entries(j) = bclid;
920 ++j;
921 alreadyAdded = true;
922 }
923 prev_bclid = bclid;
924 }
925 }
926};
927
928template <class local_matrix_type>
930 private:
931 using scalar_type = typename local_matrix_type::value_type;
932 using local_ordinal_type = typename local_matrix_type::ordinal_type;
933 using memory_space = typename local_matrix_type::memory_space;
934 using results_view = Kokkos::View<DecisionType*, memory_space>;
935 using block_indices_view_type = Kokkos::View<local_ordinal_type*, memory_space>;
936 using permutation_type = Kokkos::View<local_ordinal_type*, memory_space>;
937
938 using rowptr_type = typename local_matrix_type::row_map_type::non_const_type;
939 using ATS = KokkosKernels::ArithTraits<local_ordinal_type>;
940
941 local_matrix_type A;
945
948
949 public:
950 MergeCountFunctor(local_matrix_type& A_, local_ordinal_type blockSize_, block_indices_view_type ghosted_point_to_block_, rowptr_type& merged_rowptr_)
951 : A(A_)
952 , blockSize(blockSize_)
953 , ghosted_point_to_block(ghosted_point_to_block_)
954 , merged_rowptr(merged_rowptr_)
956 permutation = permutation_type("permutation", A.nnz());
957 }
958
959 KOKKOS_INLINE_FUNCTION
960 void operator()(const local_ordinal_type brlid, local_ordinal_type& nnz_graph, const bool& final) const {
961 // column lids for all rows in the block
962 auto block_clids = Kokkos::subview(A.graph.entries, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
963 A.graph.row_map(blockSize * (brlid + 1))));
964 // set up a permutation index
965 auto block_permutation = Kokkos::subview(permutation, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
966 A.graph.row_map(blockSize * (brlid + 1))));
967 for (size_t i = 0; i < block_permutation.extent(0); ++i)
968 block_permutation(i) = i;
969 // get permutation for sorted column indices of the entire block
970 auto comparator = comparison.getComparator(brlid);
971 Misc::serialHeapSort(block_permutation, comparator);
972
973 local_ordinal_type prev_bclid = -1;
974 bool alreadyAdded = false;
975
976 // loop over all sorted entries in block
977 auto offset = A.graph.row_map(blockSize * brlid);
978 for (size_t i = 0; i < block_permutation.extent(0); ++i) {
979 auto idx = offset + block_permutation(i);
980 auto clid = A.graph.entries(idx);
981 auto bclid = ghosted_point_to_block(clid);
982
983 // unseen block column index
984 if (bclid > prev_bclid)
985 alreadyAdded = false;
986
987 // add entry to graph
988 if (!alreadyAdded) {
989 ++nnz_graph;
990 alreadyAdded = true;
991#ifdef MUELU_COALESCE_DROP_DEBUG
992 Kokkos::printf("%5d ", bclid);
993#endif
994 }
995 prev_bclid = bclid;
996 }
997#ifdef MUELU_COALESCE_DROP_DEBUG
998 Kokkos::printf("\n");
999#endif
1000 if (final)
1001 merged_rowptr(brlid + 1) = nnz_graph;
1002 }
1003};
1004
1005template <class local_matrix_type>
1007 private:
1008 using scalar_type = typename local_matrix_type::value_type;
1009 using local_ordinal_type = typename local_matrix_type::ordinal_type;
1010 using local_graph_type = typename local_matrix_type::staticcrsgraph_type;
1011 using memory_space = typename local_matrix_type::memory_space;
1012 using results_view = Kokkos::View<DecisionType*, memory_space>;
1013 using ATS = KokkosKernels::ArithTraits<scalar_type>;
1014 using OTS = KokkosKernels::ArithTraits<local_ordinal_type>;
1015 using block_indices_view_type = Kokkos::View<local_ordinal_type*, memory_space>;
1016 using permutation_type = Kokkos::View<local_ordinal_type*, memory_space>;
1017 using magnitudeType = typename ATS::magnitudeType;
1018
1019 local_matrix_type A;
1022 local_matrix_type mergedA;
1023 const scalar_type zero = ATS::zero();
1024 const scalar_type one = ATS::one();
1025
1028
1029 public:
1030 MergeFillFunctor(local_matrix_type& A_, local_ordinal_type blockSize_, block_indices_view_type ghosted_point_to_block_, local_matrix_type& mergedA_)
1031 : A(A_)
1032 , blockSize(blockSize_)
1033 , ghosted_point_to_block(ghosted_point_to_block_)
1034 , mergedA(mergedA_)
1036 permutation = permutation_type("permutation", A.nnz());
1037 }
1038
1039 KOKKOS_INLINE_FUNCTION
1040 void operator()(const local_ordinal_type brlid) const {
1041 // column lids for all rows in the block
1042 auto block_clids = Kokkos::subview(A.graph.entries, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
1043 A.graph.row_map(blockSize * (brlid + 1))));
1044 // set up a permuatation index
1045 auto block_permutation = Kokkos::subview(permutation, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
1046 A.graph.row_map(blockSize * (brlid + 1))));
1047 for (size_t i = 0; i < block_permutation.extent(0); ++i)
1048 block_permutation(i) = i;
1049 // get permutation for sorted column indices of the entire block
1050 auto comparator = comparison.getComparator(brlid);
1051 Misc::serialHeapSort(block_permutation, comparator);
1052
1053 local_ordinal_type prev_bclid = -1;
1054 bool alreadyAdded = false;
1055 local_ordinal_type j = mergedA.graph.row_map(brlid);
1056
1057 // loop over all sorted entries in block
1058 auto offset = A.graph.row_map(blockSize * brlid);
1059 for (size_t i = 0; i < block_permutation.extent(0); ++i) {
1060 auto idx = offset + block_permutation(i);
1061 auto clid = A.graph.entries(idx);
1062 auto bclid = ghosted_point_to_block(clid);
1063
1064 // unseen block column index
1065 if (bclid > prev_bclid)
1066 alreadyAdded = false;
1067
1068 // add entry to graph
1069 if (!alreadyAdded) {
1070 mergedA.graph.entries(j) = bclid;
1071 mergedA.values(j) = one;
1072 ++j;
1073 alreadyAdded = true;
1074 }
1075 prev_bclid = bclid;
1076 }
1077 }
1078};
1079
1080template <class local_matrix_type, class local_graph_type>
1082 private:
1083 using scalar_type = typename local_matrix_type::value_type;
1084 using local_ordinal_type = typename local_matrix_type::ordinal_type;
1085 using memory_space = typename local_matrix_type::memory_space;
1086 using results_view = Kokkos::View<DecisionType*, memory_space>;
1087
1088 local_matrix_type A;
1090 local_graph_type graph;
1091
1092 public:
1093 GraphConstruction(local_matrix_type& A_, results_view& results_, local_graph_type& graph_)
1094 : A(A_)
1095 , results(results_)
1096 , graph(graph_) {}
1097
1098 KOKKOS_INLINE_FUNCTION
1099 void operator()(const local_ordinal_type rlid) const {
1100 auto rowA = A.row(rlid);
1101 size_t row_start = A.graph.row_map(rlid);
1102 local_ordinal_type jj = 0;
1103 local_ordinal_type graph_offset = graph.row_map(rlid);
1104 for (local_ordinal_type k = 0; k < rowA.length; ++k) {
1105 if (results(row_start + k) == KEEP) {
1106 graph.entries(graph_offset + jj) = rowA.colidx(k);
1107 ++jj;
1108 }
1109 }
1110 }
1111};
1112
1113} // namespace MueLu::MatrixConstruction
1114
1115#endif
BlockRowComparison(local_matrix_type &A_, local_ordinal_type bsize_, block_indices_view_type ghosted_point_to_block_)
typename local_matrix_type::ordinal_type local_ordinal_type
KOKKOS_INLINE_FUNCTION comparator_type getComparator(local_ordinal_type brlid) const
Kokkos::View< local_ordinal_type *, memory_space > block_indices_view_type
typename local_matrix_type::memory_space memory_space
GraphConstruction(local_matrix_type &A_, results_view &results_, local_graph_type &graph_)
typename local_matrix_type::value_type scalar_type
typename local_matrix_type::memory_space memory_space
Kokkos::View< DecisionType *, memory_space > results_view
typename local_matrix_type::ordinal_type local_ordinal_type
KOKKOS_INLINE_FUNCTION void operator()(const local_ordinal_type rlid) const
typename local_matrix_type::memory_space memory_space
typename local_matrix_type::value_type scalar_type
MergeCountFunctor(local_matrix_type &A_, local_ordinal_type blockSize_, block_indices_view_type ghosted_point_to_block_, rowptr_type &merged_rowptr_)
typename local_matrix_type::row_map_type::non_const_type rowptr_type
KokkosKernels::ArithTraits< local_ordinal_type > ATS
Kokkos::View< DecisionType *, memory_space > results_view
Kokkos::View< local_ordinal_type *, memory_space > block_indices_view_type
KOKKOS_INLINE_FUNCTION void operator()(const local_ordinal_type brlid, local_ordinal_type &nnz_graph, const bool &final) const
Kokkos::View< local_ordinal_type *, memory_space > permutation_type
typename local_matrix_type::ordinal_type local_ordinal_type
BlockRowComparison< local_matrix_type > comparison
typename local_matrix_type::value_type scalar_type
Kokkos::View< local_ordinal_type *, memory_space > block_indices_view_type
typename local_matrix_type::staticcrsgraph_type local_graph_type
typename local_matrix_type::ordinal_type local_ordinal_type
typename local_matrix_type::memory_space memory_space
KokkosKernels::ArithTraits< scalar_type > ATS
Kokkos::View< DecisionType *, memory_space > results_view
Kokkos::View< local_ordinal_type *, memory_space > permutation_type
KokkosKernels::ArithTraits< local_ordinal_type > OTS
BlockRowComparison< local_matrix_type > comparison
KOKKOS_INLINE_FUNCTION void operator()(const local_ordinal_type brlid) const
MergeFillFunctor(local_matrix_type &A_, local_ordinal_type blockSize_, block_indices_view_type ghosted_point_to_block_, local_matrix_type &mergedA_)
PointwiseCountingFunctor(local_matrix_type &A_, results_view &results_, rowptr_type &rowptr_, bool firstFunctor_, functor_type &functor_)
PointwiseCountingFunctor(local_matrix_type &A_, results_view &results_, rowptr_type &rowptr_, functor_type &functor_)
KOKKOS_INLINE_FUNCTION void operator()(const local_ordinal_type rlid, local_ordinal_type &nnz, const bool &final) const
Functor that executes a sequence of sub-functors on each row for a problem with blockSize == 1.
typename local_matrix_type::memory_space memory_space
PointwiseCountingFunctor(local_matrix_type &A_, results_view &results_, rowptr_type &rowptr_, bool firstFunctor_, functor_type &functor_, remaining_functor_types &... remainingFunctors_)
Kokkos::View< DecisionType *, memory_space > results_view
KOKKOS_INLINE_FUNCTION void operator()(const local_ordinal_type rlid, local_ordinal_type &nnz, const bool &final) const
typename local_matrix_type::ordinal_type local_ordinal_type
typename local_matrix_type::row_map_type::non_const_type rowptr_type
PointwiseCountingFunctor< local_matrix_type, remaining_functor_types... > remainingFunctors
PointwiseCountingFunctor(local_matrix_type &A_, results_view &results_, rowptr_type &rowptr_, functor_type &functor_, remaining_functor_types &... remainingFunctors_)
Functor does not reuse the graph of the matrix for a problem with blockSize == 1.
Kokkos::View< DecisionType *, memory_space > results_view
PointwiseFillNoReuseFunctor(local_matrix_type &A_, results_view &results_, local_matrix_type &filteredA_, magnitudeType dirichletThreshold_)
KOKKOS_INLINE_FUNCTION void operator()(const local_ordinal_type rlid) const
Functor that fills the filtered matrix while reusing the graph of the matrix before dropping,...
KOKKOS_INLINE_FUNCTION void operator()(const local_ordinal_type rlid) const
Kokkos::View< DecisionType *, memory_space > results_view
typename local_matrix_type::ordinal_type local_ordinal_type
PointwiseFillReuseFunctor(local_matrix_type &A_, results_view &results_, local_matrix_type &filteredA_, local_graph_type &graph_, magnitudeType dirichletThreshold_)
KOKKOS_INLINE_FUNCTION void join(Kokkos::pair< local_ordinal_type, local_ordinal_type > &dest, const Kokkos::pair< local_ordinal_type, local_ordinal_type > &src) const
KOKKOS_INLINE_FUNCTION void operator()(const local_ordinal_type brlid, Kokkos::pair< local_ordinal_type, local_ordinal_type > &nnz, const bool &final) const
KOKKOS_INLINE_FUNCTION void operatorRow(const local_ordinal_type rlid) const
VectorCountingFunctor(local_matrix_type &A_, local_ordinal_type blockSize_, block_indices_view_type ghosted_point_to_block_, results_view &results_, rowptr_type &filtered_rowptr_, rowptr_type &graph_rowptr_, functor_type &functor_)
Functor that executes a sequence of sub-functors on each block of rows.
VectorCountingFunctor(local_matrix_type &A_, local_ordinal_type blockSize_, block_indices_view_type ghosted_point_to_block_, results_view &results_, rowptr_type &filtered_rowptr_, rowptr_type &graph_rowptr_, functor_type &functor_, remaining_functor_types &... remainingFunctors_)
typename local_matrix_type::row_map_type::non_const_type rowptr_type
KOKKOS_INLINE_FUNCTION void operator()(const local_ordinal_type brlid, Kokkos::pair< local_ordinal_type, local_ordinal_type > &nnz, const bool &final) const
KokkosKernels::ArithTraits< local_ordinal_type > ATS
Kokkos::View< local_ordinal_type *, memory_space > block_indices_view_type
KOKKOS_INLINE_FUNCTION void join(Kokkos::pair< local_ordinal_type, local_ordinal_type > &dest, const Kokkos::pair< local_ordinal_type, local_ordinal_type > &src) const
VectorCountingFunctor< local_matrix_type, remaining_functor_types... > remainingFunctors
Kokkos::View< local_ordinal_type *, memory_space > permutation_type
typename local_matrix_type::ordinal_type local_ordinal_type
KOKKOS_INLINE_FUNCTION void operatorRow(const local_ordinal_type rlid) const
typename local_matrix_type::memory_space memory_space
Kokkos::View< DecisionType *, memory_space > results_view
KokkosKernels::ArithTraits< local_ordinal_type > OTS
Kokkos::View< local_ordinal_type *, memory_space > block_indices_view_type
typename local_matrix_type::ordinal_type local_ordinal_type
typename local_matrix_type::memory_space memory_space
Kokkos::View< DecisionType *, memory_space > results_view
BlockRowComparison< local_matrix_type > comparison
KokkosKernels::ArithTraits< scalar_type > ATS
KOKKOS_INLINE_FUNCTION void operator()(const local_ordinal_type brlid) const
VectorFillFunctor(local_matrix_type &A_, local_ordinal_type blockSize_, block_indices_view_type ghosted_point_to_block_, results_view &results_, local_matrix_type &filteredA_, local_graph_type &graph_, magnitudeType dirichletThreshold_)
Kokkos::View< local_ordinal_type *, memory_space > permutation_type
typename local_matrix_type::staticcrsgraph_type local_graph_type
typename local_matrix_type::value_type scalar_type
KOKKOS_INLINE_FUNCTION void serialHeapSort(view_type &v, comparator_type comparator)
KOKKOS_INLINE_FUNCTION bool operator()(size_t x, size_t y) const
Kokkos::View< local_ordinal_type *, memory_space > block_indices_view_type
KOKKOS_INLINE_FUNCTION Comparator(const local_matrix_type2 &A_, local_ordinal_type bsize_, local_ordinal_type brlid_, block_indices_view_type ghosted_point_to_block_)