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 "Kokkos_ArithTraits.hpp"
15
17
18#ifdef MUELU_COALESCE_DROP_DEBUG
19// For demangling function names
20#include <cxxabi.h>
21#endif
22
34template <class local_matrix_type, class functor_type, class... remaining_functor_types>
36 private:
37 using scalar_type = typename local_matrix_type::value_type;
38 using local_ordinal_type = typename local_matrix_type::ordinal_type;
39 using memory_space = typename local_matrix_type::memory_space;
40 using results_view = Kokkos::View<DecisionType*, memory_space>;
41
42 using rowptr_type = typename local_matrix_type::row_map_type::non_const_type;
43
44 local_matrix_type A;
47 functor_type functor;
48 PointwiseCountingFunctor<local_matrix_type, remaining_functor_types...> remainingFunctors;
50
51#ifdef MUELU_COALESCE_DROP_DEBUG
52 std::string functorName;
53#endif
54
55 public:
56 PointwiseCountingFunctor(local_matrix_type& A_, results_view& results_, rowptr_type& rowptr_, functor_type& functor_, remaining_functor_types&... remainingFunctors_)
57 : A(A_)
58 , results(results_)
59 , rowptr(rowptr_)
60 , functor(functor_)
61 , remainingFunctors(A_, results_, rowptr_, false, remainingFunctors_...)
62 , firstFunctor(true) {
63#ifdef MUELU_COALESCE_DROP_DEBUG
64 std::string mangledFunctorName = typeid(decltype(functor)).name();
65 int status = 0;
66 char* demangledFunctorName = 0;
67 demangledFunctorName = abi::__cxa_demangle(mangledFunctorName.c_str(), 0, 0, &status);
68 functorName = demangledFunctorName;
69#endif
70 }
71
72 PointwiseCountingFunctor(local_matrix_type& A_, results_view& results_, rowptr_type& rowptr_, bool firstFunctor_, functor_type& functor_, remaining_functor_types&... remainingFunctors_)
73 : A(A_)
74 , results(results_)
75 , rowptr(rowptr_)
76 , functor(functor_)
77 , remainingFunctors(A_, results_, rowptr_, false, remainingFunctors_...)
78 , firstFunctor(firstFunctor_) {
79#ifdef MUELU_COALESCE_DROP_DEBUG
80 std::string mangledFunctorName = typeid(decltype(functor)).name();
81 int status = 0;
82 char* demangledFunctorName = 0;
83 demangledFunctorName = abi::__cxa_demangle(mangledFunctorName.c_str(), 0, 0, &status);
84 functorName = demangledFunctorName;
85#endif
86 }
87
88 KOKKOS_INLINE_FUNCTION
89 void operator()(const local_ordinal_type rlid, local_ordinal_type& nnz, const bool& final) const {
90#ifdef MUELU_COALESCE_DROP_DEBUG
91 if (firstFunctor) {
92 Kokkos::printf("\nStarting on row %d\n", rlid);
93
94 auto row = A.rowConst(rlid);
95
96 Kokkos::printf("indices: ");
97 for (local_ordinal_type k = 0; k < row.length; ++k) {
98 auto clid = row.colidx(k);
99 Kokkos::printf("%5d ", clid);
100 }
101 Kokkos::printf("\n");
102
103 Kokkos::printf("values: ");
104 for (local_ordinal_type k = 0; k < row.length; ++k) {
105 auto val = row.value(k);
106 Kokkos::printf("%5f ", val);
107 }
108 Kokkos::printf("\n");
109 }
110#endif
111
112 functor(rlid);
113
114#ifdef MUELU_COALESCE_DROP_DEBUG
115 {
116 Kokkos::printf("%s\n", functorName.c_str());
117
118 auto row = A.rowConst(rlid);
119 const size_t offset = A.graph.row_map(rlid);
120
121 Kokkos::printf("decisions: ");
122 for (local_ordinal_type k = 0; k < row.length; ++k) {
123 Kokkos::printf("%5d ", results(offset + k));
124 }
125 Kokkos::printf("\n");
126 }
127#endif
128
129 remainingFunctors(rlid, nnz, final);
130 }
131};
132
133template <class local_matrix_type, class functor_type>
134class PointwiseCountingFunctor<local_matrix_type, functor_type> {
135 private:
136 using scalar_type = typename local_matrix_type::value_type;
137 using local_ordinal_type = typename local_matrix_type::ordinal_type;
138 using memory_space = typename local_matrix_type::memory_space;
139 using results_view = Kokkos::View<DecisionType*, memory_space>;
140
141 using rowptr_type = typename local_matrix_type::row_map_type::non_const_type;
142
143 local_matrix_type A;
146 functor_type functor;
148
149#ifdef MUELU_COALESCE_DROP_DEBUG
150 std::string functorName;
151#endif
152
153 public:
154 PointwiseCountingFunctor(local_matrix_type& A_, results_view& results_, rowptr_type& rowptr_, functor_type& functor_)
155 : A(A_)
156 , results(results_)
157 , rowptr(rowptr_)
158 , functor(functor_)
159 , firstFunctor(true) {
160#ifdef MUELU_COALESCE_DROP_DEBUG
161 std::string mangledFunctorName = typeid(decltype(functor)).name();
162 int status = 0;
163 char* demangledFunctorName = 0;
164 demangledFunctorName = abi::__cxa_demangle(mangledFunctorName.c_str(), 0, 0, &status);
165 functorName = demangledFunctorName;
166#endif
167 }
168
169 PointwiseCountingFunctor(local_matrix_type& A_, results_view& results_, rowptr_type& rowptr_, bool firstFunctor_, functor_type& functor_)
170 : A(A_)
171 , results(results_)
172 , rowptr(rowptr_)
173 , functor(functor_)
174 , firstFunctor(firstFunctor_) {
175#ifdef MUELU_COALESCE_DROP_DEBUG
176 std::string mangledFunctorName = typeid(decltype(functor)).name();
177 int status = 0;
178 char* demangledFunctorName = 0;
179 demangledFunctorName = abi::__cxa_demangle(mangledFunctorName.c_str(), 0, 0, &status);
180 functorName = demangledFunctorName;
181#endif
182 }
183
184 KOKKOS_INLINE_FUNCTION
185 void operator()(const local_ordinal_type rlid, local_ordinal_type& nnz, const bool& final) const {
186#ifdef MUELU_COALESCE_DROP_DEBUG
187 if (firstFunctor) {
188 Kokkos::printf("\nStarting on row %d\n", rlid);
189
190 auto row = A.rowConst(rlid);
191
192 Kokkos::printf("indices: ");
193 for (local_ordinal_type k = 0; k < row.length; ++k) {
194 auto clid = row.colidx(k);
195 Kokkos::printf("%5d ", clid);
196 }
197 Kokkos::printf("\n");
198
199 Kokkos::printf("values: ");
200 for (local_ordinal_type k = 0; k < row.length; ++k) {
201 auto val = row.value(k);
202 Kokkos::printf("%5f ", val);
203 }
204 Kokkos::printf("\n");
205 }
206#endif
207
208 functor(rlid);
209
210#ifdef MUELU_COALESCE_DROP_DEBUG
211 Kokkos::printf("%s\n", functorName);
212
213 auto row = A.rowConst(rlid);
214 const size_t offset = A.graph.row_map(rlid);
215
216 Kokkos::printf("decisions: ");
217 for (local_ordinal_type k = 0; k < row.length; ++k) {
218 Kokkos::printf("%5d ", results(offset + k));
219 }
220
221 Kokkos::printf("\n");
222 Kokkos::printf("Done with row %d\n", rlid);
223#endif
224
225 size_t start = A.graph.row_map(rlid);
226 size_t end = A.graph.row_map(rlid + 1);
227 for (size_t i = start; i < end; ++i) {
228 if (results(i) == KEEP) {
229 ++nnz;
230 }
231 }
232 if (final)
233 rowptr(rlid + 1) = nnz;
234 }
235};
236
245template <class local_matrix_type, class local_graph_type, bool lumping>
247 private:
248 using scalar_type = typename local_matrix_type::value_type;
249 using local_ordinal_type = typename local_matrix_type::ordinal_type;
250 using memory_space = typename local_matrix_type::memory_space;
251 using results_view = Kokkos::View<DecisionType*, memory_space>;
252 using ATS = Kokkos::ArithTraits<scalar_type>;
253 using magnitudeType = typename ATS::magnitudeType;
254
255 local_matrix_type A;
257 local_matrix_type filteredA;
258 local_graph_type graph;
260 const scalar_type zero = ATS::zero();
261 const scalar_type one = ATS::one();
262
263 public:
264 PointwiseFillReuseFunctor(local_matrix_type& A_, results_view& results_, local_matrix_type& filteredA_, local_graph_type& graph_, magnitudeType dirichletThreshold_)
265 : A(A_)
266 , results(results_)
267 , filteredA(filteredA_)
268 , graph(graph_)
269 , dirichletThreshold(dirichletThreshold_) {}
270
271 KOKKOS_INLINE_FUNCTION
272 void operator()(const local_ordinal_type rlid) const {
273 auto rowA = A.row(rlid);
274 size_t row_start = A.graph.row_map(rlid);
275 auto rowFilteredA = filteredA.row(rlid);
276 local_ordinal_type j = 0;
277 local_ordinal_type jj = 0;
278 local_ordinal_type graph_offset = graph.row_map(rlid);
279 scalar_type diagCorrection = zero;
280 local_ordinal_type diagOffset = -1;
281 for (local_ordinal_type k = 0; k < rowA.length; ++k) {
282 if constexpr (lumping) {
283 local_ordinal_type clid = rowA.colidx(k);
284 if (rlid == clid) {
285 diagOffset = j;
286 }
287 }
288 if (results(row_start + k) == KEEP) {
289 rowFilteredA.colidx(j) = rowA.colidx(k);
290 rowFilteredA.value(j) = rowA.value(k);
291 ++j;
292 graph.entries(graph_offset + jj) = rowA.colidx(k);
293 ++jj;
294 } else if constexpr (lumping) {
295 diagCorrection += rowA.value(k);
296 rowFilteredA.colidx(j) = rowA.colidx(k);
297 rowFilteredA.value(j) = zero;
298 ++j;
299 } else {
300 rowFilteredA.colidx(j) = rowA.colidx(k);
301 rowFilteredA.value(j) = zero;
302 ++j;
303 }
304 }
305 if constexpr (lumping) {
306 rowFilteredA.value(diagOffset) += diagCorrection;
307 if ((dirichletThreshold >= 0.0) && (ATS::real(rowFilteredA.value(diagOffset)) <= dirichletThreshold))
308 rowFilteredA.value(diagOffset) = one;
309 }
310 }
311};
312
320template <class local_matrix_type, bool lumping>
322 private:
323 using scalar_type = typename local_matrix_type::value_type;
324 using local_ordinal_type = typename local_matrix_type::ordinal_type;
325 using memory_space = typename local_matrix_type::memory_space;
326 using results_view = Kokkos::View<DecisionType*, memory_space>;
327 using ATS = Kokkos::ArithTraits<scalar_type>;
328 using magnitudeType = typename ATS::magnitudeType;
329
330 local_matrix_type A;
332 local_matrix_type filteredA;
334 const scalar_type zero = ATS::zero();
335 const scalar_type one = ATS::one();
336
337 public:
338 PointwiseFillNoReuseFunctor(local_matrix_type& A_, results_view& results_, local_matrix_type& filteredA_, magnitudeType dirichletThreshold_)
339 : A(A_)
340 , results(results_)
341 , filteredA(filteredA_)
342 , dirichletThreshold(dirichletThreshold_) {}
343
344 KOKKOS_INLINE_FUNCTION
345 void operator()(const local_ordinal_type rlid) const {
346 auto rowA = A.row(rlid);
347 size_t K = A.graph.row_map(rlid);
348 auto rowFilteredA = filteredA.row(rlid);
349 local_ordinal_type j = 0;
350 scalar_type diagCorrection = zero;
351 local_ordinal_type diagOffset = -1;
352 for (local_ordinal_type k = 0; k < rowA.length; ++k) {
353 if constexpr (lumping) {
354 local_ordinal_type clid = rowA.colidx(k);
355 if (rlid == clid) {
356 diagOffset = j;
357 }
358 }
359 if (results(K + k) == KEEP) {
360 rowFilteredA.colidx(j) = rowA.colidx(k);
361 rowFilteredA.value(j) = rowA.value(k);
362 ++j;
363 } else if constexpr (lumping) {
364 diagCorrection += rowA.value(k);
365 }
366 }
367 if constexpr (lumping) {
368 rowFilteredA.value(diagOffset) += diagCorrection;
369 if ((dirichletThreshold >= 0.0) && (ATS::real(rowFilteredA.value(diagOffset)) <= dirichletThreshold))
370 rowFilteredA.value(diagOffset) = one;
371 }
372 }
373};
374
375template <class local_matrix_type>
377 public:
378 using local_ordinal_type = typename local_matrix_type::ordinal_type;
379 using memory_space = typename local_matrix_type::memory_space;
380 using block_indices_view_type = Kokkos::View<local_ordinal_type*, memory_space>;
381
382 local_matrix_type A;
385
386 public:
387 BlockRowComparison(local_matrix_type& A_, local_ordinal_type bsize_, block_indices_view_type ghosted_point_to_block_)
388 : A(A_)
389 , bsize(bsize_)
390 , ghosted_point_to_block(ghosted_point_to_block_) {}
391
392 template <class local_matrix_type2>
393 struct Comparator {
394 private:
395 using local_ordinal_type = typename local_matrix_type2::ordinal_type;
396 using memory_space = typename local_matrix_type2::memory_space;
397 using block_indices_view_type = Kokkos::View<local_ordinal_type*, memory_space>;
398
399 const local_matrix_type2 A;
402
403 public:
404 KOKKOS_INLINE_FUNCTION
405 Comparator(const local_matrix_type2& A_, local_ordinal_type bsize_, local_ordinal_type brlid_, block_indices_view_type ghosted_point_to_block_)
406 : A(A_)
407 , offset(A_.graph.row_map(bsize_ * brlid_))
408 , ghosted_point_to_block(ghosted_point_to_block_) {}
409
410 KOKKOS_INLINE_FUNCTION
411 bool operator()(size_t x, size_t y) const {
412 return ghosted_point_to_block(A.graph.entries(offset + x)) < ghosted_point_to_block(A.graph.entries(offset + y));
413 }
414 };
415
417
418 KOKKOS_INLINE_FUNCTION
422};
423
434template <class local_matrix_type,
435 class functor_type,
436 class... remaining_functor_types>
438 private:
439 using scalar_type = typename local_matrix_type::value_type;
440 using local_ordinal_type = typename local_matrix_type::ordinal_type;
441 using memory_space = typename local_matrix_type::memory_space;
442 using results_view = Kokkos::View<DecisionType*, memory_space>;
443 using block_indices_view_type = Kokkos::View<local_ordinal_type*, memory_space>;
444 using permutation_type = Kokkos::View<local_ordinal_type*, memory_space>;
445
446 using rowptr_type = typename local_matrix_type::row_map_type::non_const_type;
447 using ATS = Kokkos::ArithTraits<local_ordinal_type>;
448
449 local_matrix_type A;
455
456 functor_type functor;
457
460
461 VectorCountingFunctor<local_matrix_type, remaining_functor_types...> remainingFunctors;
462
463#ifdef MUELU_COALESCE_DROP_DEBUG
464 std::string functorName;
465#endif
466
467 public:
468 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_)
469 : A(A_)
470 , blockSize(blockSize_)
471 , ghosted_point_to_block(ghosted_point_to_block_)
472 , results(results_)
473 , filtered_rowptr(filtered_rowptr_)
474 , graph_rowptr(graph_rowptr_)
475 , functor(functor_)
477 , remainingFunctors(A_, blockSize_, ghosted_point_to_block_, results_, filtered_rowptr_, graph_rowptr_, remainingFunctors_...) {
478 permutation = permutation_type("permutation", A.nnz());
479#ifdef MUELU_COALESCE_DROP_DEBUG
480 std::string mangledFunctorName = typeid(decltype(functor)).name();
481 int status = 0;
482 char* demangledFunctorName = 0;
483 demangledFunctorName = abi::__cxa_demangle(mangledFunctorName.c_str(), 0, 0, &status);
484 functorName = demangledFunctorName;
485#endif
486 }
487
488 KOKKOS_INLINE_FUNCTION
489 void join(Kokkos::pair<local_ordinal_type, local_ordinal_type>& dest, const Kokkos::pair<local_ordinal_type, local_ordinal_type>& src) const {
490 dest.first += src.first;
491 dest.second += src.second;
492 }
493
494 KOKKOS_INLINE_FUNCTION
495 void operatorRow(const local_ordinal_type rlid) const {
496 functor(rlid);
497 remainingFunctors.operatorRow(rlid);
498 }
499
500 KOKKOS_INLINE_FUNCTION
501 void operator()(const local_ordinal_type brlid, Kokkos::pair<local_ordinal_type, local_ordinal_type>& nnz, const bool& final) const {
502 auto nnz_filtered = &nnz.first;
503 auto nnz_graph = &nnz.second;
504
505#ifdef MUELU_COALESCE_DROP_DEBUG
506 Kokkos::printf("\nStarting on block row %d\n", brlid);
507#endif
508 for (local_ordinal_type rlid = blockSize * brlid; rlid < blockSize * (brlid + 1); ++rlid) {
509#ifdef MUELU_COALESCE_DROP_DEBUG
510 {
511 Kokkos::printf("\nStarting on row %d\n", rlid);
512
513 auto row = A.rowConst(rlid);
514
515 Kokkos::printf("indices: ");
516 for (local_ordinal_type k = 0; k < row.length; ++k) {
517 auto clid = row.colidx(k);
518 Kokkos::printf("%5d ", clid);
519 }
520 Kokkos::printf("\n");
521
522 Kokkos::printf("values: ");
523 for (local_ordinal_type k = 0; k < row.length; ++k) {
524 auto val = row.value(k);
525 Kokkos::printf("%5f ", val);
526 }
527 Kokkos::printf("\n");
528 }
529#endif
530
531 functor(rlid);
532 remainingFunctors.operatorRow(rlid);
533
534#ifdef MUELU_COALESCE_DROP_DEBUG
535 {
536 Kokkos::printf("%s\n", functorName.c_str());
537
538 auto row = A.rowConst(rlid);
539 const size_t offset = A.graph.row_map(rlid);
540
541 Kokkos::printf("decisions: ");
542 for (local_ordinal_type k = 0; k < row.length; ++k) {
543 Kokkos::printf("%5d ", results(offset + k));
544 }
545 Kokkos::printf("\n");
546 }
547#endif
548
549#ifdef MUELU_COALESCE_DROP_DEBUG
550 Kokkos::printf("Done with row %d\n", rlid);
551#endif
552
553 size_t start = A.graph.row_map(rlid);
554 size_t end = A.graph.row_map(rlid + 1);
555 for (size_t i = start; i < end; ++i) {
556 if (results(i) == KEEP) {
557 ++(*nnz_filtered);
558 }
559 }
560 if (final)
561 filtered_rowptr(rlid + 1) = *nnz_filtered;
562 }
563
564#ifdef MUELU_COALESCE_DROP_DEBUG
565 Kokkos::printf("Done with block row %d\nGraph indices ", brlid);
566#endif
567
568 // column lids for all rows in the block
569 auto block_clids = Kokkos::subview(A.graph.entries, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
570 A.graph.row_map(blockSize * (brlid + 1))));
571 // set up a permutatation index
572 auto block_permutation = Kokkos::subview(permutation, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
573 A.graph.row_map(blockSize * (brlid + 1))));
574 for (size_t i = 0; i < block_permutation.extent(0); ++i)
575 block_permutation(i) = i;
576 // get permuatation for sorted column indices of the entire block
577 auto comparator = comparison.getComparator(brlid);
578 Misc::serialHeapSort(block_permutation, comparator);
579
580 local_ordinal_type prev_bclid = -1;
581 bool alreadyAdded = false;
582
583 // loop over all sorted entries in block
584 auto offset = A.graph.row_map(blockSize * brlid);
585 for (size_t i = 0; i < block_permutation.extent(0); ++i) {
586 auto idx = offset + block_permutation(i);
587 auto clid = A.graph.entries(idx);
588 auto bclid = ghosted_point_to_block(clid);
589
590 // unseen block column index
591 if (bclid > prev_bclid)
592 alreadyAdded = false;
593
594 // add entry to graph
595 if (!alreadyAdded && (results(idx) == KEEP)) {
596 ++(*nnz_graph);
597 alreadyAdded = true;
598#ifdef MUELU_COALESCE_DROP_DEBUG
599 Kokkos::printf("%5d ", bclid);
600#endif
601 }
602 prev_bclid = bclid;
603 }
604#ifdef MUELU_COALESCE_DROP_DEBUG
605 Kokkos::printf("\n");
606#endif
607 if (final)
608 graph_rowptr(brlid + 1) = *nnz_graph;
609 }
610};
611
612template <class local_matrix_type,
613 class functor_type>
614class VectorCountingFunctor<local_matrix_type, functor_type> {
615 private:
616 using scalar_type = typename local_matrix_type::value_type;
617 using local_ordinal_type = typename local_matrix_type::ordinal_type;
618 using memory_space = typename local_matrix_type::memory_space;
619 using results_view = Kokkos::View<DecisionType*, memory_space>;
620 using block_indices_view_type = Kokkos::View<local_ordinal_type*, memory_space>;
621 using permutation_type = Kokkos::View<local_ordinal_type*, memory_space>;
622
623 using rowptr_type = typename local_matrix_type::row_map_type::non_const_type;
624 using ATS = Kokkos::ArithTraits<local_ordinal_type>;
625
626 local_matrix_type A;
632
634 functor_type functor;
635
636#ifdef MUELU_COALESCE_DROP_DEBUG
637 std::string functorName;
638#endif
639
642
643 public:
644 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_)
645 : A(A_)
646 , blockSize(blockSize_)
647 , ghosted_point_to_block(ghosted_point_to_block_)
648 , results(results_)
649 , filtered_rowptr(filtered_rowptr_)
650 , graph_rowptr(graph_rowptr_)
651 , functor(functor_)
653 permutation = permutation_type("permutation", A.nnz());
654#ifdef MUELU_COALESCE_DROP_DEBUG
655 std::string mangledFunctorName = typeid(decltype(functor)).name();
656 int status = 0;
657 char* demangledFunctorName = 0;
658 demangledFunctorName = abi::__cxa_demangle(mangledFunctorName.c_str(), 0, 0, &status);
659 functorName = demangledFunctorName;
660#endif
661 }
662
663 KOKKOS_INLINE_FUNCTION
664 void join(Kokkos::pair<local_ordinal_type, local_ordinal_type>& dest, const Kokkos::pair<local_ordinal_type, local_ordinal_type>& src) const {
665 dest.first += src.first;
666 dest.second += src.second;
667 }
668
669 KOKKOS_INLINE_FUNCTION
670 void operatorRow(const local_ordinal_type rlid) const {
671 functor(rlid);
672 }
673
674 KOKKOS_INLINE_FUNCTION
675 void operator()(const local_ordinal_type brlid, Kokkos::pair<local_ordinal_type, local_ordinal_type>& nnz, const bool& final) const {
676 auto nnz_filtered = &nnz.first;
677 auto nnz_graph = &nnz.second;
678
679#ifdef MUELU_COALESCE_DROP_DEBUG
680 Kokkos::printf("\nStarting on block row %d\n", brlid);
681#endif
682 for (local_ordinal_type rlid = blockSize * brlid; rlid < blockSize * (brlid + 1); ++rlid) {
683#ifdef MUELU_COALESCE_DROP_DEBUG
684 {
685 Kokkos::printf("\nStarting on row %d\n", rlid);
686
687 auto row = A.rowConst(rlid);
688
689 Kokkos::printf("indices: ");
690 for (local_ordinal_type k = 0; k < row.length; ++k) {
691 auto clid = row.colidx(k);
692 Kokkos::printf("%5d ", clid);
693 }
694 Kokkos::printf("\n");
695
696 Kokkos::printf("values: ");
697 for (local_ordinal_type k = 0; k < row.length; ++k) {
698 auto val = row.value(k);
699 Kokkos::printf("%5f ", val);
700 }
701 Kokkos::printf("\n");
702 }
703#endif
704
705 functor(rlid);
706
707#ifdef MUELU_COALESCE_DROP_DEBUG
708 {
709 Kokkos::printf("%s\n", functorName.c_str());
710
711 auto row = A.rowConst(rlid);
712 const size_t offset = A.graph.row_map(rlid);
713
714 Kokkos::printf("decisions: ");
715 for (local_ordinal_type k = 0; k < row.length; ++k) {
716 Kokkos::printf("%5d ", results(offset + k));
717 }
718 Kokkos::printf("\n");
719 }
720#endif
721
722#ifdef MUELU_COALESCE_DROP_DEBUG
723 Kokkos::printf("Done with row %d\n", rlid);
724#endif
725
726 size_t start = A.graph.row_map(rlid);
727 size_t end = A.graph.row_map(rlid + 1);
728 for (size_t i = start; i < end; ++i) {
729 if (results(i) == KEEP) {
730 ++(*nnz_filtered);
731 }
732 }
733 if (final)
734 filtered_rowptr(rlid + 1) = *nnz_filtered;
735 }
736
737#ifdef MUELU_COALESCE_DROP_DEBUG
738 Kokkos::printf("Done with block row %d\nGraph indices ", brlid);
739#endif
740
741 // column lids for all rows in the block
742 auto block_clids = Kokkos::subview(A.graph.entries, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
743 A.graph.row_map(blockSize * (brlid + 1))));
744 // set up a permutation index
745 auto block_permutation = Kokkos::subview(permutation, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
746 A.graph.row_map(blockSize * (brlid + 1))));
747 for (size_t i = 0; i < block_permutation.extent(0); ++i)
748 block_permutation(i) = i;
749 // get permutation for sorted column indices of the entire block
750 auto comparator = comparison.getComparator(brlid);
751 Misc::serialHeapSort(block_permutation, comparator);
752
753 local_ordinal_type prev_bclid = -1;
754 bool alreadyAdded = false;
755
756 // loop over all sorted entries in block
757 auto offset = A.graph.row_map(blockSize * brlid);
758 for (size_t i = 0; i < block_permutation.extent(0); ++i) {
759 auto idx = offset + block_permutation(i);
760 auto clid = A.graph.entries(idx);
761 auto bclid = ghosted_point_to_block(clid);
762
763 // unseen block column index
764 if (bclid > prev_bclid)
765 alreadyAdded = false;
766
767 // add entry to graph
768 if (!alreadyAdded && (results(idx) == KEEP)) {
769 ++(*nnz_graph);
770 alreadyAdded = true;
771#ifdef MUELU_COALESCE_DROP_DEBUG
772 Kokkos::printf("%5d ", bclid);
773#endif
774 }
775 prev_bclid = bclid;
776 }
777#ifdef MUELU_COALESCE_DROP_DEBUG
778 Kokkos::printf("\n");
779#endif
780 if (final)
781 graph_rowptr(brlid + 1) = *nnz_graph;
782 }
783};
784
792template <class local_matrix_type, bool lumping, bool reuse>
794 private:
795 using scalar_type = typename local_matrix_type::value_type;
796 using local_ordinal_type = typename local_matrix_type::ordinal_type;
797 using local_graph_type = typename local_matrix_type::staticcrsgraph_type;
798 using memory_space = typename local_matrix_type::memory_space;
799 using results_view = Kokkos::View<DecisionType*, memory_space>;
800 using ATS = Kokkos::ArithTraits<scalar_type>;
801 using OTS = Kokkos::ArithTraits<local_ordinal_type>;
802 using block_indices_view_type = Kokkos::View<local_ordinal_type*, memory_space>;
803 using permutation_type = Kokkos::View<local_ordinal_type*, memory_space>;
804 using magnitudeType = typename ATS::magnitudeType;
805
806 local_matrix_type A;
810 local_matrix_type filteredA;
813 const scalar_type zero = ATS::zero();
814 const scalar_type one = ATS::one();
815
818
819 public:
820 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_)
821 : A(A_)
822 , blockSize(blockSize_)
823 , ghosted_point_to_block(ghosted_point_to_block_)
824 , results(results_)
825 , filteredA(filteredA_)
826 , graph(graph_)
827 , dirichletThreshold(dirichletThreshold_)
829 permutation = permutation_type("permutation", A.nnz());
830 }
831
832 KOKKOS_INLINE_FUNCTION
833 void operator()(const local_ordinal_type brlid) const {
834 for (local_ordinal_type rlid = blockSize * brlid; rlid < blockSize * (brlid + 1); ++rlid) {
835 auto rowA = A.row(rlid);
836 size_t row_start = A.graph.row_map(rlid);
837 auto rowFilteredA = filteredA.row(rlid);
838 local_ordinal_type j = 0;
839 scalar_type diagCorrection = zero;
840 local_ordinal_type diagOffset = -1;
841 for (local_ordinal_type k = 0; k < rowA.length; ++k) {
842 if constexpr (lumping) {
843 local_ordinal_type clid = rowA.colidx(k);
844 if (rlid == clid) {
845 diagOffset = j;
846 }
847 }
848 if (results(row_start + k) == KEEP) {
849 rowFilteredA.colidx(j) = rowA.colidx(k);
850 rowFilteredA.value(j) = rowA.value(k);
851 ++j;
852 } else if constexpr (lumping) {
853 diagCorrection += rowA.value(k);
854 if constexpr (reuse) {
855 rowFilteredA.colidx(j) = rowA.colidx(k);
856 rowFilteredA.value(j) = zero;
857 ++j;
858 }
859 } else if constexpr (reuse) {
860 rowFilteredA.colidx(j) = rowA.colidx(k);
861 rowFilteredA.value(j) = zero;
862 ++j;
863 }
864 }
865 if constexpr (lumping) {
866 rowFilteredA.value(diagOffset) += diagCorrection;
867 if ((dirichletThreshold >= 0.0) && (ATS::real(rowFilteredA.value(diagOffset)) <= dirichletThreshold))
868 rowFilteredA.value(diagOffset) = one;
869 }
870 }
871
872 // column lids for all rows in the block
873 auto block_clids = Kokkos::subview(A.graph.entries, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
874 A.graph.row_map(blockSize * (brlid + 1))));
875 // set up a permuatation index
876 auto block_permutation = Kokkos::subview(permutation, Kokkos::make_pair(A.graph.row_map(blockSize * brlid),
877 A.graph.row_map(blockSize * (brlid + 1))));
878 for (size_t i = 0; i < block_permutation.extent(0); ++i)
879 block_permutation(i) = i;
880 // get permutation for sorted column indices of the entire block
881 auto comparator = comparison.getComparator(brlid);
882 Misc::serialHeapSort(block_permutation, comparator);
883
884 local_ordinal_type prev_bclid = -1;
885 bool alreadyAdded = false;
886 local_ordinal_type j = graph.row_map(brlid);
887
888 // loop over all sorted entries in block
889 auto offset = A.graph.row_map(blockSize * brlid);
890 for (size_t i = 0; i < block_permutation.extent(0); ++i) {
891 auto idx = offset + block_permutation(i);
892 auto clid = A.graph.entries(idx);
893 auto bclid = ghosted_point_to_block(clid);
894
895 // unseen block column index
896 if (bclid > prev_bclid)
897 alreadyAdded = false;
898
899 // add entry to graph
900 if (!alreadyAdded && (results(idx) == KEEP)) {
901 graph.entries(j) = bclid;
902 ++j;
903 alreadyAdded = true;
904 }
905 prev_bclid = bclid;
906 }
907 }
908};
909
910} // namespace MueLu::MatrixConstruction
911
912#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
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
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_)
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
Kokkos::View< DecisionType *, memory_space > results_view
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_)
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
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
Kokkos::View< local_ordinal_type *, memory_space > block_indices_view_type
Kokkos::ArithTraits< local_ordinal_type > OTS
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
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_)