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
653 functor_type functor;
654
655#ifdef MUELU_COALESCE_DROP_DEBUG
656 std::string functorName;
657#endif
658
661
662 public:
663 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_)
664 : A(A_)
665 , blockSize(blockSize_)
666 , ghosted_point_to_block(ghosted_point_to_block_)
667 , results(results_)
668 , filtered_rowptr(filtered_rowptr_)
669 , graph_rowptr(graph_rowptr_)
670 , functor(functor_)
672 permutation = permutation_type("permutation", A.nnz());
673#ifdef MUELU_COALESCE_DROP_DEBUG
674 std::string mangledFunctorName = typeid(decltype(functor)).name();
675 int status = 0;
676 char* demangledFunctorName = 0;
677 demangledFunctorName = abi::__cxa_demangle(mangledFunctorName.c_str(), 0, 0, &status);
678 functorName = demangledFunctorName;
679#endif
680 }
681
682 KOKKOS_INLINE_FUNCTION
683 void join(Kokkos::pair<local_ordinal_type, local_ordinal_type>& dest, const Kokkos::pair<local_ordinal_type, local_ordinal_type>& src) const {
684 dest.first += src.first;
685 dest.second += src.second;
686 }
687
688 KOKKOS_INLINE_FUNCTION
689 void operatorRow(const local_ordinal_type rlid) const {
690 functor(rlid);
691 }
692
693 KOKKOS_INLINE_FUNCTION
694 void operator()(const local_ordinal_type brlid, Kokkos::pair<local_ordinal_type, local_ordinal_type>& nnz, const bool& final) const {
695 auto nnz_filtered = &nnz.first;
696 auto nnz_graph = &nnz.second;
697
698#ifdef MUELU_COALESCE_DROP_DEBUG
699 Kokkos::printf("\nStarting on block row %d\n", brlid);
700#endif
701 for (local_ordinal_type rlid = blockSize * brlid; rlid < blockSize * (brlid + 1); ++rlid) {
702#ifdef MUELU_COALESCE_DROP_DEBUG
703 {
704 Kokkos::printf("\nStarting on row %d\n", rlid);
705
706 auto row = A.rowConst(rlid);
707
708 Kokkos::printf("indices: ");
709 for (local_ordinal_type k = 0; k < row.length; ++k) {
710 auto clid = row.colidx(k);
711 Kokkos::printf("%5d ", clid);
712 }
713 Kokkos::printf("\n");
714
715 Kokkos::printf("values: ");
716 for (local_ordinal_type k = 0; k < row.length; ++k) {
717 auto val = row.value(k);
718 Kokkos::printf("%5f ", val);
719 }
720 Kokkos::printf("\n");
721 }
722#endif
723
724 functor(rlid);
725
726#ifdef MUELU_COALESCE_DROP_DEBUG
727 {
728 Kokkos::printf("%s\n", functorName.c_str());
729
730 auto row = A.rowConst(rlid);
731 const size_t offset = A.graph.row_map(rlid);
732
733 Kokkos::printf("decisions: ");
734 for (local_ordinal_type k = 0; k < row.length; ++k) {
735 Kokkos::printf("%5d ", results(offset + k));
736 }
737 Kokkos::printf("\n");
738 }
739#endif
740
741#ifdef MUELU_COALESCE_DROP_DEBUG
742 Kokkos::printf("Done with row %d\n", rlid);
743#endif
744
745 size_t start = A.graph.row_map(rlid);
746 size_t end = A.graph.row_map(rlid + 1);
747 for (size_t i = start; i < end; ++i) {
748 if (results(i) == KEEP) {
749 ++(*nnz_filtered);
750 }
751 }
752 if (final)
753 filtered_rowptr(rlid + 1) = *nnz_filtered;
754 }
755
756#ifdef MUELU_COALESCE_DROP_DEBUG
757 Kokkos::printf("Done with block row %d\nGraph indices ", brlid);
758#endif
759
760 // column lids for all rows in the block
761 auto block_clids = Kokkos::subview(A.graph.entries, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
762 A.graph.row_map(blockSize * (brlid + 1))));
763 // set up a permutation index
764 auto block_permutation = Kokkos::subview(permutation, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
765 A.graph.row_map(blockSize * (brlid + 1))));
766 for (size_t i = 0; i < block_permutation.extent(0); ++i)
767 block_permutation(i) = i;
768 // get permutation for sorted column indices of the entire block
769 auto comparator = comparison.getComparator(brlid);
770 Misc::serialHeapSort(block_permutation, comparator);
771
772 local_ordinal_type prev_bclid = -1;
773 bool alreadyAdded = false;
774
775 // loop over all sorted entries in block
776 auto offset = A.graph.row_map(blockSize * brlid);
777 for (size_t i = 0; i < block_permutation.extent(0); ++i) {
778 auto idx = offset + block_permutation(i);
779 auto clid = A.graph.entries(idx);
780 auto bclid = ghosted_point_to_block(clid);
781
782 // unseen block column index
783 if (bclid > prev_bclid)
784 alreadyAdded = false;
785
786 // add entry to graph
787 if (!alreadyAdded && (results(idx) == KEEP)) {
788 ++(*nnz_graph);
789 alreadyAdded = true;
790#ifdef MUELU_COALESCE_DROP_DEBUG
791 Kokkos::printf("%5d ", bclid);
792#endif
793 }
794 prev_bclid = bclid;
795 }
796#ifdef MUELU_COALESCE_DROP_DEBUG
797 Kokkos::printf("\n");
798#endif
799 if (final)
800 graph_rowptr(brlid + 1) = *nnz_graph;
801 }
802};
803
811template <class local_matrix_type, bool lumping, bool reuse>
813 private:
814 using scalar_type = typename local_matrix_type::value_type;
815 using local_ordinal_type = typename local_matrix_type::ordinal_type;
816 using local_graph_type = typename local_matrix_type::staticcrsgraph_type;
817 using memory_space = typename local_matrix_type::memory_space;
818 using results_view = Kokkos::View<DecisionType*, memory_space>;
819 using ATS = KokkosKernels::ArithTraits<scalar_type>;
820 using OTS = KokkosKernels::ArithTraits<local_ordinal_type>;
821 using block_indices_view_type = Kokkos::View<local_ordinal_type*, memory_space>;
822 using permutation_type = Kokkos::View<local_ordinal_type*, memory_space>;
823 using magnitudeType = typename ATS::magnitudeType;
824
825 local_matrix_type A;
829 local_matrix_type filteredA;
832 const scalar_type zero = ATS::zero();
833 const scalar_type one = ATS::one();
834
837
838 public:
839 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_)
840 : A(A_)
841 , blockSize(blockSize_)
842 , ghosted_point_to_block(ghosted_point_to_block_)
843 , results(results_)
844 , filteredA(filteredA_)
845 , graph(graph_)
846 , dirichletThreshold(dirichletThreshold_)
848 permutation = permutation_type("permutation", A.nnz());
849 }
850
851 KOKKOS_INLINE_FUNCTION
852 void operator()(const local_ordinal_type brlid) const {
853 for (local_ordinal_type rlid = blockSize * brlid; rlid < blockSize * (brlid + 1); ++rlid) {
854 auto rowA = A.row(rlid);
855 size_t row_start = A.graph.row_map(rlid);
856 auto rowFilteredA = filteredA.row(rlid);
857 local_ordinal_type j = 0;
858 scalar_type diagCorrection = zero;
859 local_ordinal_type diagOffset = -1;
860 for (local_ordinal_type k = 0; k < rowA.length; ++k) {
861 if constexpr (lumping) {
862 local_ordinal_type clid = rowA.colidx(k);
863 if (rlid == clid) {
864 diagOffset = j;
865 }
866 }
867 if (results(row_start + k) == KEEP) {
868 rowFilteredA.colidx(j) = rowA.colidx(k);
869 rowFilteredA.value(j) = rowA.value(k);
870 ++j;
871 } else if constexpr (lumping) {
872 diagCorrection += rowA.value(k);
873 if constexpr (reuse) {
874 rowFilteredA.colidx(j) = rowA.colidx(k);
875 rowFilteredA.value(j) = zero;
876 ++j;
877 }
878 } else if constexpr (reuse) {
879 rowFilteredA.colidx(j) = rowA.colidx(k);
880 rowFilteredA.value(j) = zero;
881 ++j;
882 }
883 }
884 if constexpr (lumping) {
885 rowFilteredA.value(diagOffset) += diagCorrection;
886 if ((dirichletThreshold >= 0.0) && (ATS::real(rowFilteredA.value(diagOffset)) <= dirichletThreshold))
887 rowFilteredA.value(diagOffset) = one;
888 }
889 }
890
891 // column lids for all rows in the block
892 auto block_clids = Kokkos::subview(A.graph.entries, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
893 A.graph.row_map(blockSize * (brlid + 1))));
894 // set up a permuatation index
895 auto block_permutation = Kokkos::subview(permutation, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
896 A.graph.row_map(blockSize * (brlid + 1))));
897 for (size_t i = 0; i < block_permutation.extent(0); ++i)
898 block_permutation(i) = i;
899 // get permutation for sorted column indices of the entire block
900 auto comparator = comparison.getComparator(brlid);
901 Misc::serialHeapSort(block_permutation, comparator);
902
903 local_ordinal_type prev_bclid = -1;
904 bool alreadyAdded = false;
905 local_ordinal_type j = graph.row_map(brlid);
906
907 // loop over all sorted entries in block
908 auto offset = A.graph.row_map(blockSize * brlid);
909 for (size_t i = 0; i < block_permutation.extent(0); ++i) {
910 auto idx = offset + block_permutation(i);
911 auto clid = A.graph.entries(idx);
912 auto bclid = ghosted_point_to_block(clid);
913
914 // unseen block column index
915 if (bclid > prev_bclid)
916 alreadyAdded = false;
917
918 // add entry to graph
919 if (!alreadyAdded && (results(idx) == KEEP)) {
920 graph.entries(j) = bclid;
921 ++j;
922 alreadyAdded = true;
923 }
924 prev_bclid = bclid;
925 }
926 }
927};
928
929template <class local_matrix_type>
931 private:
932 using scalar_type = typename local_matrix_type::value_type;
933 using local_ordinal_type = typename local_matrix_type::ordinal_type;
934 using memory_space = typename local_matrix_type::memory_space;
935 using results_view = Kokkos::View<DecisionType*, memory_space>;
936 using block_indices_view_type = Kokkos::View<local_ordinal_type*, memory_space>;
937 using permutation_type = Kokkos::View<local_ordinal_type*, memory_space>;
938
939 using rowptr_type = typename local_matrix_type::row_map_type::non_const_type;
940 using ATS = KokkosKernels::ArithTraits<local_ordinal_type>;
941
942 local_matrix_type A;
946
949
950 public:
951 MergeCountFunctor(local_matrix_type& A_, local_ordinal_type blockSize_, block_indices_view_type ghosted_point_to_block_, rowptr_type& merged_rowptr_)
952 : A(A_)
953 , blockSize(blockSize_)
954 , ghosted_point_to_block(ghosted_point_to_block_)
955 , merged_rowptr(merged_rowptr_)
957 permutation = permutation_type("permutation", A.nnz());
958 }
959
960 KOKKOS_INLINE_FUNCTION
961 void operator()(const local_ordinal_type brlid, local_ordinal_type& nnz_graph, const bool& final) const {
962 // column lids for all rows in the block
963 auto block_clids = Kokkos::subview(A.graph.entries, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
964 A.graph.row_map(blockSize * (brlid + 1))));
965 // set up a permutation index
966 auto block_permutation = Kokkos::subview(permutation, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
967 A.graph.row_map(blockSize * (brlid + 1))));
968 for (size_t i = 0; i < block_permutation.extent(0); ++i)
969 block_permutation(i) = i;
970 // get permutation for sorted column indices of the entire block
971 auto comparator = comparison.getComparator(brlid);
972 Misc::serialHeapSort(block_permutation, comparator);
973
974 local_ordinal_type prev_bclid = -1;
975 bool alreadyAdded = false;
976
977 // loop over all sorted entries in block
978 auto offset = A.graph.row_map(blockSize * brlid);
979 for (size_t i = 0; i < block_permutation.extent(0); ++i) {
980 auto idx = offset + block_permutation(i);
981 auto clid = A.graph.entries(idx);
982 auto bclid = ghosted_point_to_block(clid);
983
984 // unseen block column index
985 if (bclid > prev_bclid)
986 alreadyAdded = false;
987
988 // add entry to graph
989 if (!alreadyAdded) {
990 ++nnz_graph;
991 alreadyAdded = true;
992#ifdef MUELU_COALESCE_DROP_DEBUG
993 Kokkos::printf("%5d ", bclid);
994#endif
995 }
996 prev_bclid = bclid;
997 }
998#ifdef MUELU_COALESCE_DROP_DEBUG
999 Kokkos::printf("\n");
1000#endif
1001 if (final)
1002 merged_rowptr(brlid + 1) = nnz_graph;
1003 }
1004};
1005
1006template <class local_matrix_type>
1008 private:
1009 using scalar_type = typename local_matrix_type::value_type;
1010 using local_ordinal_type = typename local_matrix_type::ordinal_type;
1011 using local_graph_type = typename local_matrix_type::staticcrsgraph_type;
1012 using memory_space = typename local_matrix_type::memory_space;
1013 using results_view = Kokkos::View<DecisionType*, memory_space>;
1014 using ATS = KokkosKernels::ArithTraits<scalar_type>;
1015 using OTS = KokkosKernels::ArithTraits<local_ordinal_type>;
1016 using block_indices_view_type = Kokkos::View<local_ordinal_type*, memory_space>;
1017 using permutation_type = Kokkos::View<local_ordinal_type*, memory_space>;
1018 using magnitudeType = typename ATS::magnitudeType;
1019
1020 local_matrix_type A;
1023 local_matrix_type mergedA;
1024 const scalar_type zero = ATS::zero();
1025 const scalar_type one = ATS::one();
1026
1029
1030 public:
1031 MergeFillFunctor(local_matrix_type& A_, local_ordinal_type blockSize_, block_indices_view_type ghosted_point_to_block_, local_matrix_type& mergedA_)
1032 : A(A_)
1033 , blockSize(blockSize_)
1034 , ghosted_point_to_block(ghosted_point_to_block_)
1035 , mergedA(mergedA_)
1037 permutation = permutation_type("permutation", A.nnz());
1038 }
1039
1040 KOKKOS_INLINE_FUNCTION
1041 void operator()(const local_ordinal_type brlid) const {
1042 // column lids for all rows in the block
1043 auto block_clids = Kokkos::subview(A.graph.entries, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
1044 A.graph.row_map(blockSize * (brlid + 1))));
1045 // set up a permuatation index
1046 auto block_permutation = Kokkos::subview(permutation, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
1047 A.graph.row_map(blockSize * (brlid + 1))));
1048 for (size_t i = 0; i < block_permutation.extent(0); ++i)
1049 block_permutation(i) = i;
1050 // get permutation for sorted column indices of the entire block
1051 auto comparator = comparison.getComparator(brlid);
1052 Misc::serialHeapSort(block_permutation, comparator);
1053
1054 local_ordinal_type prev_bclid = -1;
1055 bool alreadyAdded = false;
1056 local_ordinal_type j = mergedA.graph.row_map(brlid);
1057
1058 // loop over all sorted entries in block
1059 auto offset = A.graph.row_map(blockSize * brlid);
1060 for (size_t i = 0; i < block_permutation.extent(0); ++i) {
1061 auto idx = offset + block_permutation(i);
1062 auto clid = A.graph.entries(idx);
1063 auto bclid = ghosted_point_to_block(clid);
1064
1065 // unseen block column index
1066 if (bclid > prev_bclid)
1067 alreadyAdded = false;
1068
1069 // add entry to graph
1070 if (!alreadyAdded) {
1071 mergedA.graph.entries(j) = bclid;
1072 mergedA.values(j) = one;
1073 ++j;
1074 alreadyAdded = true;
1075 }
1076 prev_bclid = bclid;
1077 }
1078 }
1079};
1080
1081template <class local_matrix_type, class local_graph_type>
1083 private:
1084 using scalar_type = typename local_matrix_type::value_type;
1085 using local_ordinal_type = typename local_matrix_type::ordinal_type;
1086 using memory_space = typename local_matrix_type::memory_space;
1087 using results_view = Kokkos::View<DecisionType*, memory_space>;
1088
1089 local_matrix_type A;
1091 local_graph_type graph;
1092
1093 public:
1094 GraphConstruction(local_matrix_type& A_, results_view& results_, local_graph_type& graph_)
1095 : A(A_)
1096 , results(results_)
1097 , graph(graph_) {}
1098
1099 KOKKOS_INLINE_FUNCTION
1100 void operator()(const local_ordinal_type rlid) const {
1101 auto rowA = A.row(rlid);
1102 size_t row_start = A.graph.row_map(rlid);
1103 local_ordinal_type jj = 0;
1104 local_ordinal_type graph_offset = graph.row_map(rlid);
1105 for (local_ordinal_type k = 0; k < rowA.length; ++k) {
1106 if (results(row_start + k) == KEEP) {
1107 graph.entries(graph_offset + jj) = rowA.colidx(k);
1108 ++jj;
1109 }
1110 }
1111 }
1112};
1113
1114} // namespace MueLu::MatrixConstruction
1115
1116#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_)