MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_CGSolver_def.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 #ifndef MUELU_CGSOLVER_DEF_HPP
47 #define MUELU_CGSOLVER_DEF_HPP
48 
49 #include <Xpetra_MatrixFactory.hpp>
50 #include <Xpetra_MatrixMatrix.hpp>
51 
52 #include "MueLu_Utilities.hpp"
53 #include "MueLu_Constraint.hpp"
54 #include "MueLu_Monitor.hpp"
55 
56 #include "MueLu_CGSolver_decl.hpp"
57 
58 namespace MueLu {
59 
60 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
62  : nIts_(Its) {}
63 
64 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
65 void CGSolver<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Iterate(const Matrix& Aref, const Constraint& C, const Matrix& P0, RCP<Matrix>& finalP) const {
66  // Note: this function matrix notations follow Saad's "Iterative methods", ed. 2, pg. 246
67  // So, X is the unknown prolongator, P's are conjugate directions, Z's are preconditioned P's
68  PrintMonitor m(*this, "CG iterations");
69 
70  if (nIts_ == 0) {
71  finalP = MatrixFactory2::BuildCopy(rcpFromRef(P0));
72  return;
73  }
74 
75  RCP<const Matrix> A = rcpFromRef(Aref);
77  bool useTpetra = (A->getRowMap()->lib() == Xpetra::UseTpetra);
78 
79  Teuchos::FancyOStream& mmfancy = this->GetOStream(Statistics2);
80 
82 
83  RCP<Matrix> X, P, R, Z, AP;
84  RCP<Matrix> newX, tmpAP;
85 #ifndef TWO_ARG_MATRIX_ADD
86  RCP<Matrix> newR, newP;
87 #endif
88 
89  SC oldRZ, newRZ, alpha, beta, app;
90 
91  // T is used only for projecting onto
92  RCP<CrsMatrix> T_ = CrsMatrixFactory::Build(C.GetPattern());
93  T_->fillComplete(P0.getDomainMap(), P0.getRangeMap());
94  RCP<Matrix> T = rcp(new CrsMatrixWrap(T_));
95 
96  // Initial P0 would only be used for multiplication
97  X = rcp_const_cast<Matrix>(rcpFromRef(P0));
98 
99  tmpAP = MatrixMatrix::Multiply(*A, false, *X, false, mmfancy, true /*doFillComplete*/, true /*optimizeStorage*/);
100  C.Apply(*tmpAP, *T);
101 
102  // R_0 = -A*X_0
104 
105  R->scale(-one);
106 
107  // Z_0 = M^{-1}R_0
109  Utilities::MyOldScaleMatrix(*Z, D, true, true, false);
110 
111  // P_0 = Z_0
113 
114  oldRZ = Utilities::Frobenius(*R, *Z);
115 
116  for (size_t i = 0; i < nIts_; i++) {
117  // AP = constrain(A*P)
118  if (i == 0 || useTpetra) {
119  // Construct the MxM pattern from scratch
120  // This is done by default for Tpetra as the three argument version requires tmpAP
121  // to *not* be locally indexed which defeats the purpose
122  // TODO: need a three argument Tpetra version which allows reuse of already fill-completed matrix
123  tmpAP = MatrixMatrix::Multiply(*A, false, *P, false, mmfancy, true /*doFillComplete*/, true /*optimizeStorage*/);
124  } else {
125  // Reuse the MxM pattern
126  tmpAP = MatrixMatrix::Multiply(*A, false, *P, false, tmpAP, mmfancy, true /*doFillComplete*/, true /*optimizeStorage*/);
127  }
128  C.Apply(*tmpAP, *T);
129  AP = T;
130 
131  app = Utilities::Frobenius(*AP, *P);
133  // It happens, for instance, if P = 0
134  // For example, if we use TentativePFactory for both nonzero pattern and initial guess
135  // I think it might also happen because of numerical breakdown, but we don't test for that yet
136  if (i == 0)
137  X = MatrixFactory2::BuildCopy(rcpFromRef(P0));
138  break;
139  }
140 
141  // alpha = (R_i, Z_i)/(A*P_i, P_i)
142  alpha = oldRZ / app;
143  this->GetOStream(Runtime1, 1) << "alpha = " << alpha << std::endl;
144 
145  // X_{i+1} = X_i + alpha*P_i
146 #ifndef TWO_ARG_MATRIX_ADD
147  newX = Teuchos::null;
148  MatrixMatrix::TwoMatrixAdd(*P, false, alpha, *X, false, one, newX, mmfancy);
149  newX->fillComplete(P0.getDomainMap(), P0.getRangeMap());
150  X.swap(newX);
151 #else
152  MatrixMatrix::TwoMatrixAdd(*P, false, alpha, *X, one);
153 #endif
154 
155  if (i == nIts_ - 1)
156  break;
157 
158  // R_{i+1} = R_i - alpha*A*P_i
159 #ifndef TWO_ARG_MATRIX_ADD
160  newR = Teuchos::null;
161  MatrixMatrix::TwoMatrixAdd(*AP, false, -alpha, *R, false, one, newR, mmfancy);
162  newR->fillComplete(P0.getDomainMap(), P0.getRangeMap());
163  R.swap(newR);
164 #else
165  MatrixMatrix::TwoMatrixAdd(*AP, false, -alpha, *R, one);
166 #endif
167 
168  // Z_{i+1} = M^{-1} R_{i+1}
169  Z = MatrixFactory2::BuildCopy(R);
170  Utilities::MyOldScaleMatrix(*Z, D, true, true, false);
171 
172  // beta = (R_{i+1}, Z_{i+1})/(R_i, Z_i)
173  newRZ = Utilities::Frobenius(*R, *Z);
174  beta = newRZ / oldRZ;
175 
176  // P_{i+1} = Z_{i+1} + beta*P_i
177 #ifndef TWO_ARG_MATRIX_ADD
178  newP = Teuchos::null;
179  MatrixMatrix::TwoMatrixAdd(*P, false, beta, *Z, false, one, newP, mmfancy);
180  newP->fillComplete(P0.getDomainMap(), P0.getRangeMap());
181  P.swap(newP);
182 #else
183  MatrixMatrix::TwoMatrixAdd(*Z, false, one, *P, beta);
184 #endif
185 
186  oldRZ = newRZ;
187  }
188 
189  finalP = X;
190 }
191 
192 } // namespace MueLu
193 
194 #endif // ifndef MUELU_CGSOLVER_DECL_HPP
static void MyOldScaleMatrix(Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, const Teuchos::ArrayRCP< const Scalar > &scalingVector, bool doInverse=true, bool doFillComplete=true, bool doOptimizeStorage=true)
Constraint space information for the potential prolongator.
void swap(RCP< T > &r_ptr)
RCP< const CrsGraph > GetPattern() const
Print even more statistics.
void Iterate(const Matrix &A, const Constraint &C, const Matrix &P0, RCP< Matrix > &P) const
Iterate.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
static Teuchos::ArrayRCP< Scalar > GetMatrixDiagonal_arcp(const Matrix &A)
Extract Matrix Diagonal.
static RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > BuildCopy(const RCP< const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > A)
void Apply(const Matrix &P, Matrix &Projected) const
Apply constraint.
Scalar SC
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.
Description of what is happening (more verbose)