MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_DenseConstraint_def.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_DENSECONSTRAINT_DEF_HPP
11#define MUELU_DENSECONSTRAINT_DEF_HPP
12
13#include <Xpetra_Map.hpp>
14#include <Xpetra_MapFactory.hpp>
15#include <Xpetra_Matrix.hpp>
16#include <Xpetra_MultiVector.hpp>
17#include <Xpetra_CrsGraph.hpp>
18#include "MueLu_Exceptions.hpp"
20#include "Xpetra_ConfigDefs.hpp"
21#include "Xpetra_MatrixFactory.hpp"
22
23namespace MueLu {
24
25template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
27 DenseConstraint(const RCP<MultiVector>& B,
28 const RCP<MultiVector>& Bc,
29 RCP<const CrsGraph> Ppattern,
30 const std::string& solverType) {
31 this->SetPattern(Ppattern);
32 B_ = B;
33 Bc_ = Bc;
34 this->SetProcRankVerbose(Ppattern->getRowMap()->getComm()->getRank());
35 Setup();
36 this->PrepareLeastSquaresSolve(solverType, /*detect_singular_blocks=*/false);
37}
38
39template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
41 using graph_t = typename CrsGraph::local_graph_type;
42 using matrix_t = typename CrsMatrix::local_matrix_type;
43 using lno_view_t = typename graph_t::row_map_type::non_const_type;
44 using lno_nnz_view_t = typename graph_t::entries_type::non_const_type;
45 using scalar_view_t = typename matrix_t::values_type::non_const_type;
46 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
47
48 auto Ppattern = this->GetPattern();
49 auto B = B_;
50 auto Bc = Bc_;
51 const size_t NSDim = Bc->getNumVectors();
52 const size_t numUnknowns = Ppattern->getLocalNumEntries();
53 const size_t numRows = Ppattern->getLocalNumRows();
54 const size_t numConstraints = numRows * NSDim;
55
56 TEUCHOS_TEST_FOR_EXCEPTION(!B->getMap()->isSameAs(*Ppattern->getRangeMap()),
58 "Maps are incompatible");
59 TEUCHOS_TEST_FOR_EXCEPTION(!Bc->getMap()->isSameAs(*Ppattern->getDomainMap()),
61 "Maps are incompatible");
62
63 auto importer = Ppattern->getImporter();
64 RCP<MultiVector> ghostedBc;
65 if (!importer.is_null()) {
66 ghostedBc = MultiVectorFactory::Build(Ppattern->getColMap(), NSDim);
67 ghostedBc->doImport(*Bc, *importer, Xpetra::INSERT);
68 } else {
69 ghostedBc = Bc;
70 }
71
72 auto lib = Ppattern->getRowMap()->lib();
73 auto comm = Ppattern->getComm();
74 GlobalOrdinal indexBase = Ppattern->getRowMap()->getIndexBase();
75 Xpetra::global_size_t global_numConstraints = Ppattern->getGlobalNumRows() * NSDim;
76 Xpetra::global_size_t global_numUnknowns = Ppattern->getGlobalNumEntries();
77 auto constraint_rowmap = MapFactory::Build(lib, global_numConstraints, numConstraints, indexBase, comm);
78 auto constraint_domainmap = MapFactory::Build(lib, global_numUnknowns, numUnknowns, indexBase, comm);
79
80 // The matrix of constraints X has size (global_numConstraints, global_numUnknowns).
81 RCP<Matrix> X;
82 {
83 auto lclPattern = Ppattern->getLocalGraphDevice();
84 auto pattern_rowptr = lclPattern.row_map;
85
86 auto lclNullspace = ghostedBc->getLocalViewDevice(Tpetra::Access::ReadOnly);
87
88 lno_view_t rowptr(Kokkos::ViewAllocateWithoutInitializing("constraint_rowptr"), numConstraints + 1);
89 LocalOrdinal nnz = NSDim * lclPattern.entries.extent(0);
90 lno_nnz_view_t colind(Kokkos::ViewAllocateWithoutInitializing("constraint_indices"), nnz);
91 scalar_view_t values(Kokkos::ViewAllocateWithoutInitializing("constraint_values"), nnz);
92
93 Kokkos::parallel_for(
94 "MueLu::DenseConstraint::buildNullspaceConstraint",
95 range_type(0, numRows + 1),
96 KOKKOS_LAMBDA(const size_t i) {
97 if (i < numRows) {
98 for (size_t k = 0; k < NSDim; ++k) {
99 rowptr(NSDim * i + k) = NSDim * lclPattern.row_map(i) + k * (lclPattern.row_map(i + 1) - lclPattern.row_map(i));
100
101 size_t l = 0;
102 for (size_t jj = lclPattern.row_map(i); jj < lclPattern.row_map(i + 1); ++jj) {
103 auto j = lclPattern.entries(jj);
104 colind(rowptr(NSDim * i + k) + l) = jj;
105 values(rowptr(NSDim * i + k) + l) = lclNullspace(j, k);
106 ++l;
107 }
108 }
109 } else {
110 rowptr(numConstraints) = nnz;
111 }
112 });
113 auto lclConstraintGraph = graph_t(colind, rowptr);
114 auto lclConstraint = matrix_t("constraint", numUnknowns, values, lclConstraintGraph);
115 X = MatrixFactory::Build(lclConstraint, constraint_rowmap, constraint_domainmap, constraint_domainmap, constraint_rowmap);
116 }
117 this->SetConstraintsMatrix(X);
118}
119
120template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
121typename Xpetra::CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::local_graph_type DenseConstraint<Scalar, LocalOrdinal, GlobalOrdinal, Node>::FindBlocks(RCP<const Xpetra::CrsGraph<LocalOrdinal, GlobalOrdinal, Node>>& /*XXt*/) {
122 using execution_space = typename Node::execution_space;
123 using range_type = Kokkos::RangePolicy<LocalOrdinal, execution_space>;
124
125 auto X = this->GetConstraintMatrix();
126 auto lclX = X->getLocalMatrixDevice();
127
128 const auto numConstraints = lclX.numRows();
129 const auto NSDim = B_->getNumVectors();
130 const auto numBlocks = numConstraints / NSDim;
131 TEUCHOS_ASSERT_EQUALITY(numBlocks * NSDim, (decltype(numBlocks))numConstraints);
132
133 using graph_type = typename CrsGraph::local_graph_type;
134 typename graph_type::row_map_type::non_const_type rowptr(Kokkos::ViewAllocateWithoutInitializing("blocks_rowptr"), numBlocks + 1);
135 typename graph_type::entries_type::non_const_type indices(Kokkos::ViewAllocateWithoutInitializing("blocks_indices"), numConstraints);
136
137 Kokkos::parallel_for(
138 "MueLu::DenseConstraint::FindBlocks", range_type(0, numBlocks), KOKKOS_LAMBDA(const LocalOrdinal blockId) {
139 const auto start = blockId * NSDim;
140 const auto end = (blockId + 1) * NSDim;
141 if (blockId == 0)
142 rowptr(0) = start;
143 rowptr(blockId + 1) = end;
144 for (auto constraintId = start; constraintId < end; ++constraintId)
145 indices(constraintId) = constraintId;
146 });
147
148 return graph_type(indices, rowptr);
149}
150
151template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
152typename Teuchos::ScalarTraits<Scalar>::magnitudeType
154 const auto one = Teuchos::ScalarTraits<Scalar>::one();
155
156 auto residual = MultiVectorFactory::Build(B_->getMap(), B_->getNumVectors());
157 P->apply(*Bc_, *residual, Teuchos::NO_TRANS);
158 residual->update(one, *B_, -one);
159 Teuchos::Array<MagnitudeType> norms(B_->getNumVectors());
160 residual->norm2(norms);
161 MagnitudeType residualNorm = Teuchos::ScalarTraits<MagnitudeType>::zero();
162 for (size_t k = 0; k < B_->getNumVectors(); ++k) {
163 residualNorm += norms[k] * norms[k];
164 }
165 return Teuchos::ScalarTraits<MagnitudeType>::squareroot(residualNorm);
166}
167
168} // namespace MueLu
169
170#endif // ifndef MUELU_DENSECONSTRAINT_DEF_HPP
MueLu::DefaultLocalOrdinal LocalOrdinal
MueLu::DefaultGlobalOrdinal GlobalOrdinal
CrsGraph::local_graph_type FindBlocks(RCP< const CrsGraph > &) override
MagnitudeType ResidualNorm(RCP< const Matrix > P) const override
Compute norm of residual B - P*Bc.
typename Teuchos::ScalarTraits< Scalar >::magnitudeType MagnitudeType
Exception throws to report incompatible objects (like maps).
Namespace for MueLu classes and methods.