MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_CGSolver_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_CGSOLVER_DEF_HPP
11#define MUELU_CGSOLVER_DEF_HPP
12
13#include <Xpetra_MatrixFactory.hpp>
14#include <Xpetra_MatrixFactory2.hpp>
15#include <Xpetra_MatrixMatrix.hpp>
16
17#include "MueLu_Utilities.hpp"
18#include "MueLu_Constraint.hpp"
19#include "MueLu_Monitor.hpp"
20
22
23namespace MueLu {
24
25template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
28
29template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
30void CGSolver<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Iterate(const Matrix& Aref, const Constraint& C, const Matrix& P0, RCP<Matrix>& finalP) const {
31 // Note: this function matrix notations follow Saad's "Iterative methods", ed. 2, pg. 246
32 // So, X is the unknown prolongator, P's are conjugate directions, Z's are preconditioned P's
33 PrintMonitor m(*this, "CG iterations");
34
35 if (nIts_ == 0) {
36 finalP = MatrixFactory2::BuildCopy(rcpFromRef(P0));
37 return;
38 }
39
40 RCP<const Matrix> A = rcpFromRef(Aref);
41 const auto rowMap = A->getRowMap();
42 auto invDiag = Xpetra::VectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(rowMap, true);
43 A->getLocalDiagCopy(*invDiag);
44 invDiag->reciprocal(*invDiag);
45
46 bool useTpetra = (A->getRowMap()->lib() == Xpetra::UseTpetra);
47
48 Teuchos::FancyOStream& mmfancy = this->GetOStream(Statistics2);
49
50 SC one = Teuchos::ScalarTraits<SC>::one();
51
52 RCP<Matrix> X, P, R, Z, AP;
53 RCP<Matrix> newX, tmpAP;
54#ifndef TWO_ARG_MATRIX_ADD
55 RCP<Matrix> newR, newP;
56#endif
57
58 SC oldRZ, newRZ, alpha, beta, app;
59
60 // T is used only for projecting onto
61 RCP<CrsMatrix> T_ = CrsMatrixFactory::Build(C.GetPattern());
62 T_->fillComplete(P0.getDomainMap(), P0.getRangeMap());
63 RCP<Matrix> T = rcp(new CrsMatrixWrap(T_));
64
65 // Initial P0 would only be used for multiplication
66 X = rcp_const_cast<Matrix>(rcpFromRef(P0));
67
68 tmpAP = MatrixMatrix::Multiply(*A, false, *X, false, mmfancy, true /*doFillComplete*/, true /*optimizeStorage*/);
69 C.Apply(*tmpAP, *T);
70
71 // R_0 = -A*X_0
72 R = Xpetra::MatrixFactory2<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(T);
73
74 R->scale(-one);
75
76 // Z_0 = M^{-1}R_0
77 Z = Xpetra::MatrixFactory2<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(R);
78 Z->leftScale(*invDiag);
79
80 // P_0 = Z_0
81 P = Xpetra::MatrixFactory2<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(Z);
82
83 oldRZ = Utilities::Frobenius(*R, *Z);
84
85 for (size_t i = 0; i < nIts_; i++) {
86 // AP = constrain(A*P)
87 if (i == 0 || useTpetra) {
88 // Construct the MxM pattern from scratch
89 // This is done by default for Tpetra as the three argument version requires tmpAP
90 // to *not* be locally indexed which defeats the purpose
91 // TODO: need a three argument Tpetra version which allows reuse of already fill-completed matrix
92 tmpAP = MatrixMatrix::Multiply(*A, false, *P, false, mmfancy, true /*doFillComplete*/, true /*optimizeStorage*/);
93 } else {
94 // Reuse the MxM pattern
95 tmpAP = MatrixMatrix::Multiply(*A, false, *P, false, tmpAP, mmfancy, true /*doFillComplete*/, true /*optimizeStorage*/);
96 }
97 C.Apply(*tmpAP, *T);
98 AP = T;
99
100 app = Utilities::Frobenius(*AP, *P);
101 if (Teuchos::ScalarTraits<SC>::magnitude(app) < Teuchos::ScalarTraits<SC>::sfmin()) {
102 // It happens, for instance, if P = 0
103 // For example, if we use TentativePFactory for both nonzero pattern and initial guess
104 // I think it might also happen because of numerical breakdown, but we don't test for that yet
105 if (i == 0)
106 X = MatrixFactory2::BuildCopy(rcpFromRef(P0));
107 break;
108 }
109
110 // alpha = (R_i, Z_i)/(A*P_i, P_i)
111 alpha = oldRZ / app;
112 this->GetOStream(Runtime1, 1) << "alpha = " << alpha << std::endl;
113
114 // X_{i+1} = X_i + alpha*P_i
115#ifndef TWO_ARG_MATRIX_ADD
116 newX = Teuchos::null;
117 MatrixMatrix::TwoMatrixAdd(*P, false, alpha, *X, false, one, newX, mmfancy);
118 newX->fillComplete(P0.getDomainMap(), P0.getRangeMap());
119 X.swap(newX);
120#else
121 MatrixMatrix::TwoMatrixAdd(*P, false, alpha, *X, one);
122#endif
123
124 if (i == nIts_ - 1)
125 break;
126
127 // R_{i+1} = R_i - alpha*A*P_i
128#ifndef TWO_ARG_MATRIX_ADD
129 newR = Teuchos::null;
130 MatrixMatrix::TwoMatrixAdd(*AP, false, -alpha, *R, false, one, newR, mmfancy);
131 newR->fillComplete(P0.getDomainMap(), P0.getRangeMap());
132 R.swap(newR);
133#else
134 MatrixMatrix::TwoMatrixAdd(*AP, false, -alpha, *R, one);
135#endif
136
137 // Z_{i+1} = M^{-1} R_{i+1}
138 Z = MatrixFactory2::BuildCopy(R);
139 Z->leftScale(*invDiag);
140
141 // beta = (R_{i+1}, Z_{i+1})/(R_i, Z_i)
142 newRZ = Utilities::Frobenius(*R, *Z);
143 beta = newRZ / oldRZ;
144
145 // P_{i+1} = Z_{i+1} + beta*P_i
146#ifndef TWO_ARG_MATRIX_ADD
147 newP = Teuchos::null;
148 MatrixMatrix::TwoMatrixAdd(*P, false, beta, *Z, false, one, newP, mmfancy);
149 newP->fillComplete(P0.getDomainMap(), P0.getRangeMap());
150 P.swap(newP);
151#else
152 MatrixMatrix::TwoMatrixAdd(*Z, false, one, *P, beta);
153#endif
154
155 oldRZ = newRZ;
156 }
157
158 finalP = X;
159}
160
161} // namespace MueLu
162
163#endif // ifndef MUELU_CGSOLVER_DECL_HPP
void Iterate(const Matrix &A, const Constraint &C, const Matrix &P0, RCP< Matrix > &P) const
Iterate.
Constraint space information for the potential prolongator.
RCP< const CrsGraph > GetPattern() const
void Apply(const Matrix &P, Matrix &Projected) const
Apply constraint.
static Scalar Frobenius(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &B)
Frobenius inner product of two matrices.
Namespace for MueLu classes and methods.
@ Statistics2
Print even more statistics.
@ Runtime1
Description of what is happening (more verbose)