48 using graph_t =
typename CrsGraph::local_graph_type;
49 using matrix_t =
typename CrsMatrix::local_matrix_type;
50 using lno_view_t =
typename graph_t::row_map_type::non_const_type;
51 using lno_nnz_view_t =
typename graph_t::entries_type::non_const_type;
52 using scalar_view_t =
typename matrix_t::values_type::non_const_type;
53 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
55 auto INVALID = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
61 auto Ppattern = this->GetPattern();
80 auto lib = Ppattern->getRowMap()->lib();
84 auto comm = Ppattern->getRowMap()->getComm();
85 if (Dc.is_null() || Dc->getRowMap()->getComm()->getSize() < comm->getSize()) {
87 Kokkos::View<GlobalOrdinal*, typename Node::memory_space> dummy(
"", 0);
88 auto big_coarse_nodal_map = MapFactory::Build(lib, INVALID, dummy, 0, comm);
89 auto big_coarse_edge_map = MapFactory::Build(lib, INVALID, dummy, 0, comm);
90 auto big_coarse_nodal_colmap = MapFactory::Build(lib, INVALID, dummy, 0, comm);
92 typename Matrix::local_matrix_device_type dummyLocalMatrix;
93 big_Dc_ = MatrixFactory::Build(dummyLocalMatrix, big_coarse_edge_map, big_coarse_nodal_colmap, big_coarse_nodal_map, big_coarse_edge_map);
96 auto big_coarse_nodal_map = MapFactory::Build(lib, INVALID, Dc->getDomainMap()->getMyGlobalIndicesDevice(), 0, comm);
97 auto big_coarse_edge_map = MapFactory::Build(lib, INVALID, Dc->getRangeMap()->getMyGlobalIndicesDevice(), 0, comm);
98 auto big_coarse_nodal_colmap = MapFactory::Build(lib, INVALID, Dc->getColMap()->getMyGlobalIndicesDevice(), 0, comm);
100 big_Dc_ = MatrixFactory::Build(Dc->getLocalMatrixDevice(), big_coarse_edge_map, big_coarse_nodal_colmap, big_coarse_nodal_map, big_coarse_edge_map);
106 TEUCHOS_TEST_FOR_EXCEPTION(!D->getRangeMap()->isSameAs(*Ppattern->getRangeMap()),
108 "Maps are incompatible");
109 TEUCHOS_TEST_FOR_EXCEPTION(!big_Dc_->getRangeMap()->isSameAs(*Ppattern->getDomainMap()),
111 "Maps are incompatible");
114 RCP<const CrsGraph> auxGraph;
116 const auto one = Teuchos::ScalarTraits<Scalar>::one();
117 auto absP = MatrixFactory::Build(Ppattern);
118 absP->setAllToScalar(one);
119 absP->fillComplete();
121 auto absDc = MatrixFactory::BuildCopy(big_Dc_);
122 absDc->setAllToScalar(one);
124 auto P_Dc = MatrixMatrix::Multiply(*absP,
false, *absDc,
false, this->GetOStream(
Statistics2),
true,
true);
125 auxGraph = P_Dc->getCrsGraph();
127 RHS_pattern_ = auxGraph;
129 GlobalOrdinal indexBase = Ppattern->getRowMap()->getIndexBase();
130 const size_t numUnknowns = Ppattern->getLocalNumEntries();
131 const size_t numRows = Ppattern->getLocalNumRows();
132 Xpetra::global_size_t global_numConstraints = auxGraph->getGlobalNumEntries();
133 Xpetra::global_size_t global_numUnknowns = Ppattern->getGlobalNumEntries();
134 const size_t numConstraints = auxGraph->getLocalNumEntries();
135 auto constraint_rowmap = MapFactory::Build(lib, global_numConstraints, numConstraints, indexBase, comm);
136 auto constraint_domainmap = MapFactory::Build(lib, global_numUnknowns, numUnknowns, indexBase, comm);
138 RCP<Matrix> ghostedDc;
139 if (!Ppattern->getImporter().is_null())
140 ghostedDc = MatrixFactory::Build(big_Dc_, *Ppattern->getImporter());
146 auto lclPattern = Ppattern->getLocalGraphDevice();
147 auto lclD0 = ghostedDc->getLocalMatrixDevice();
148 auto lclAuxGraph = auxGraph->getLocalGraphDevice();
151 lno_view_t rowptr(
"constraint_rowptr", numConstraints + 2);
153 Kokkos::parallel_for(
154 "MueLu::SparseConstraint::sparse_constraint_num_entries_per_row",
155 range_type(0, numRows),
156 KOKKOS_LAMBDA(
const size_t pattern_i) {
157 for (
size_t pattern_jj = lclPattern.row_map(pattern_i); pattern_jj < lclPattern.row_map(pattern_i + 1); ++pattern_jj) {
158 auto pattern_j = lclPattern.entries(pattern_jj);
161 for (
size_t D0_jj = lclD0.graph.row_map(pattern_j); D0_jj < lclD0.graph.row_map(pattern_j + 1); ++D0_jj) {
162 auto D0_j = lclD0.graph.entries(D0_jj);
167 for (constraint_I = lclAuxGraph.row_map(pattern_i); constraint_I < lclAuxGraph.row_map(pattern_i + 1); ++constraint_I) {
168 if (lclAuxGraph.entries(constraint_I) == D0_j)
171#ifdef HAVE_MUELU_DEBUG
172 if (lclAuxGraph.entries(constraint_I) != D0_j)
173 ::Kokkos::abort(
"Did not find entry in row of tempGraph.");
178 Kokkos::atomic_add(&rowptr(constraint_I + 2), 1);
185 Kokkos::parallel_scan(
186 "MueLu::SparseConstraint::sparse_constraint_prefix_sum",
187 range_type(1, numConstraints + 2),
188 KOKKOS_LAMBDA(
const size_t constraint_i,
size_t& partial_nnz,
bool is_final) {
189 partial_nnz += rowptr(constraint_i);
191 rowptr(constraint_i) = partial_nnz;
196 lno_nnz_view_t colind(Kokkos::ViewAllocateWithoutInitializing(
"constraint_indices"), nnz);
197 scalar_view_t values(Kokkos::ViewAllocateWithoutInitializing(
"constraint_values"), nnz);
200 Kokkos::parallel_for(
201 "MueLu::SparseConstraint::sparse_constraint_fill",
202 range_type(0, numRows),
203 KOKKOS_LAMBDA(
const size_t pattern_i) {
204 for (
size_t pattern_jj = lclPattern.row_map(pattern_i); pattern_jj < lclPattern.row_map(pattern_i + 1); ++pattern_jj) {
205 auto pattern_j = lclPattern.entries(pattern_jj);
208 for (
size_t D0_jj = lclD0.graph.row_map(pattern_j); D0_jj < lclD0.graph.row_map(pattern_j + 1); ++D0_jj) {
209 auto D0_j = lclD0.graph.entries(D0_jj);
210 auto D0_val = lclD0.values(D0_jj);
215 for (constraint_I = lclAuxGraph.row_map(pattern_i); constraint_I < lclAuxGraph.row_map(pattern_i + 1); ++constraint_I) {
216 if (lclAuxGraph.entries(constraint_I) == D0_j)
219#ifdef HAVE_MUELU_DEBUG
220 if (lclAuxGraph.entries(constraint_I) != D0_j)
221 ::Kokkos::abort(
"Did not find entry in row of tempGraph.");
227 auto constraint_jj = Kokkos::atomic_fetch_inc(&rowptr(constraint_I + 1));
228 colind(constraint_jj) = pattern_jj;
229 values(constraint_jj) = D0_val;
234 auto lclConstraintGraph = graph_t(colind, Kokkos::subview(rowptr, Kokkos::make_pair(
size_t(0), numConstraints + 1)));
235 auto lclConstraint = matrix_t(
"constraint", numUnknowns, values, lclConstraintGraph);
236 X = MatrixFactory::Build(lclConstraint, constraint_rowmap, constraint_domainmap, constraint_domainmap, constraint_rowmap);
238 this->SetConstraintsMatrix(X);
243 using execution_space =
typename Node::execution_space;
244 using range_type = Kokkos::RangePolicy<LocalOrdinal, execution_space>;
246 auto lclGraph = RHS_pattern_->getLocalGraphDevice();
249 Kokkos::parallel_reduce(
250 "MueLu::SparseConstraint::FindBlocks::CountEmptyRows", range_type(0, lclGraph.numRows()), KOKKOS_LAMBDA(
const LocalOrdinal rowId,
LocalOrdinal& emptyRows) {
251 if (lclGraph.row_map(rowId + 1) == lclGraph.row_map(rowId))
256 auto numConstraints = lclGraph.entries.extent(0);
257 using graph_type =
typename CrsGraph::local_graph_type;
258 typename graph_type::row_map_type::non_const_type rowptr(
"blocks_rowptr", lclGraph.numRows() + 1 - numEmptyRows);
259 typename graph_type::entries_type::non_const_type indices(
"blocks_indices", numConstraints);
261 Kokkos::parallel_scan(
262 "MueLu::SparseConstraint::FindBlocks::GenerateBlockRowPtr", range_type(0, lclGraph.numRows()), KOKKOS_LAMBDA(
const LocalOrdinal rowId,
LocalOrdinal& rowIdNew,
const bool is_final) {
263 if (lclGraph.row_map(rowId + 1) != lclGraph.row_map(rowId)) {
265 rowptr(rowIdNew + 1) = lclGraph.row_map(rowId + 1);
270 Kokkos::parallel_for(
271 "MueLu::SparseConstraint::FindBlocks::FillBlockIndices", range_type(0, numConstraints), KOKKOS_LAMBDA(
const LocalOrdinal constraintId) {
272 indices(constraintId) = constraintId;
275 return graph_type(indices, rowptr);