MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_GMRESSolver_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_GMRESSOLVER_DEF_HPP
47 #define MUELU_GMRESSOLVER_DEF_HPP
48 
49 #include <Teuchos_LAPACK.hpp>
50 
51 #include <Xpetra_MatrixFactory.hpp>
52 #include <Xpetra_MatrixMatrix.hpp>
53 #include <Xpetra_IO.hpp>
54 
55 #include "MueLu_GMRESSolver.hpp"
56 
57 #include "MueLu_Constraint.hpp"
58 #include "MueLu_Monitor.hpp"
59 #include "MueLu_Utilities.hpp"
60 
61 
62 namespace MueLu {
63 
64  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
66  : nIts_(Its)
67  { }
68 
69  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
70  void GMRESSolver<Scalar, LocalOrdinal, GlobalOrdinal, Node>::givapp(Scalar* c, Scalar* s, Scalar* v, int k) const {
71  for (int i = 0; i < k; i++) {
72  SC w1 = c[i]*v[i] - s[i]*v[i+1];
73  SC w2 = s[i]*v[i] + c[i]*v[i+1];
74  v[i] = w1;
75  v[i+1] = w2;
76  }
77  }
78 
79  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
80  void GMRESSolver<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Iterate(const Matrix& Aref, const Constraint& C, const Matrix& P0, RCP<Matrix>& finalP) const {
81  PrintMonitor m(*this, "GMRES iterations");
82 
83  finalP = MatrixFactory2::BuildCopy(rcpFromRef(P0));
84  if (nIts_ == 0)
85  return;
86 
88  "For now, solving Hessenberg system works only for a single iteration");
89 
91 
92  RCP<const Matrix> A = rcpFromRef(Aref);
93  //bool useTpetra = (A->getRowMap()->lib() == Xpetra::UseTpetra);
94 
95  // FIXME: Don't know why, but in the MATLAB code we have D = I. Follow that for now.
96 #if 0
98 #else
99  ArrayRCP<const SC> D(A->getNodeNumRows(), one);
100 #endif
101 
102  Teuchos::FancyOStream& mmfancy = this->GetOStream(Statistics2);
103 
104  // Initial P0 would only be used for multiplication
105  RCP<Matrix> X = rcp_const_cast<Matrix>(rcpFromRef(P0)), tmpAP, newV;
106  std::vector<RCP<Matrix> > V(nIts_+1);
107 
108  // T is used only for projecting onto
109  RCP<CrsMatrix> T_ = CrsMatrixFactory::Build(C.GetPattern());
110  T_->fillComplete(P0.getDomainMap(), P0.getRangeMap());
111  RCP<Matrix> T = rcp(new CrsMatrixWrap(T_));
112 
113  SC rho;
114  {
115  // R_0 = -D^{-1}*A*X_0
116  // V_0 = R_0 / ||R_0||_F
117  tmpAP = MatrixMatrix::Multiply(*A, false, *X, false, mmfancy, true/*doFillComplete*/, true/*optimizeStorage*/);
118  C.Apply(*tmpAP, *T);
119 
120  V[0] = MatrixFactory2::BuildCopy(T);
121  Utilities::MyOldScaleMatrix(*V[0], D, true/*doInverse*/, true/*doFillComplete*/, false/*doOptimizeStorage*/);
122 
123  rho = sqrt(Utilities::Frobenius(*V[0], *V[0]));
124 
125  V[0]->resumeFill();
126  V[0]->scale(-one/rho);
127  V[0]->fillComplete(V[0]->getDomainMap(), V[0]->getRangeMap());
128  }
129 
130  std::vector<SC> h((nIts_+1) * (nIts_+1));
131  std::vector<SC> c(nIts_+1, 0.0);
132  std::vector<SC> s(nIts_+1, 0.0);
133  std::vector<SC> g(nIts_+1, 0.0);
134  g[0] = rho;
135 
136 #define I(i,j) ((i) + (j)*(nIts_+1)) // column ordering
137  for (size_t i = 0; i < nIts_; i++) {
138  // V_{i+1} = D^{-1}*A*V_i
139  tmpAP = MatrixMatrix::Multiply(*A, false, *V[i], false, mmfancy, true/*doFillComplete*/, true/*optimizeStorage*/);
140  C.Apply(*tmpAP, *T);
141 
142  V[i+1] = MatrixFactory2::BuildCopy(T);
143  Utilities::MyOldScaleMatrix(*V[i+1], D, true/*doInverse*/, true/*doFillComplete*/, false/*doOptimizeStorage*/);
144 
145  // Update Hessenberg matrix
146  for (size_t j = 0; j <= i; j++) {
147  h[I(j,i)] = Utilities::Frobenius(*V[i+1], *V[j]);
148 
149  // V_{i+1} = V_{i+1} - h(j,i+1)*V_j
150 #ifndef TWO_ARG_MATRIX_ADD
151  newV = Teuchos::null;
152  MatrixMatrix::TwoMatrixAdd(*V[j], false, -h[I(j,i)], *V[i+1], false, one, newV, mmfancy);
153  newV->fillComplete(V[i+1]->getDomainMap(), V[i+1]->getRangeMap());
154  V[i+1].swap(newV);
155 #else
156  // FIXME: this does not work now. Fails with the following exception:
157  // what(): ../../packages/tpetra/core/ext/TpetraExt_MatrixMatrix_def.hpp:408:
158  //
159  // Throw number = 1
160  //
161  // Throw test that evaluated to true: B.isLocallyIndexed()
162  //
163  // TpetraExt::MatrixMatrix::Add(): ERROR, input matrix B must not be locally indexed
164  MatrixMatrix::TwoMatrixAdd(*V[j], false, -h[I(j,i)], *V[i+1], one);
165 #endif
166  }
167  h[I(i+1,i)] = sqrt(Utilities::Frobenius(*V[i+1], *V[i+1]));
168 
169  // NOTE: potentially we'll need some reorthogonalization code here
170  // The matching MATLAB code is
171  // normav = norm(v.num(k+1).matrix, 'fro');
172  // normav2 = h(k+1,k);
173  // if (reorth == -1 && normav + .001*normav2 == normav)
174  // for j = 1:k
175  // hr = v(:,j)'*v(:,k+1); % hr=v(:,k+1)'*v(:,j);
176  // h(j,k) = h(j,k)+hr;
177  // v(:,k+1) = v(:,k+1)-hr*v(:,j);
178  // end
179  // h(k+1,k) = norm(v(:,k+1));
180  // end
181 
182  // Check for nonsymmetric case
183  if (h[I(i+1,i)] != zero) {
184  // Normalize V_i
185  V[i+1]->resumeFill();
186  V[i+1]->scale(one/h[I(i+1,i)]);
187  V[i+1]->fillComplete(V[i+1]->getDomainMap(), V[i+1]->getRangeMap());
188  }
189 
190  if (i > 0)
191  givapp(&c[0], &s[0], &h[I(0,i)], i); // Due to column ordering &h[...] is a column
192 
193  SC nu = sqrt(h[I(i,i)]*h[I(i,i)] + h[I(i+1,i)]*h[I(i+1,i)]);
194  if (nu != zero) {
195  c[i] = h[I(i, i)] / nu;
196  s[i] = -h[I(i+1,i)] / nu;
197  h[I(i,i)] = c[i] * h[I(i,i)] - s[i] * h[I(i+1,i)];
198  h[I(i+1,i)] = zero;
199 
200  givapp(&c[i], &s[i], &g[i], 1);
201  }
202  }
203 
204  // Solve Hessenberg system
205  // y = solve(H, \rho e_1)
206  std::vector<SC> y(nIts_);
207  if (nIts_ == 1) {
208  y[0] = g[0] / h[I(0,0)];
209  }
210 #undef I
211 
212  // Compute final
213  for (size_t i = 0; i < nIts_; i++) {
214 #ifndef TWO_ARG_MATRIX_ADD
215  newV = Teuchos::null;
216  MatrixMatrix::TwoMatrixAdd(*V[i], false, y[i], *finalP, false, one, newV, mmfancy);
217  newV->fillComplete(finalP->getDomainMap(), finalP->getRangeMap());
218  finalP.swap(newV);
219 #else
220  MatrixMatrix::TwoMatrixAdd(*V[i], false, y[i], *finalP, one);
221 #endif
222  }
223  }
224 
225 } // namespace MueLu
226 
227 #endif //ifndef MUELU_GMRESSOLVER_DECL_HPP
static Teuchos::ArrayRCP< Scalar > GetMatrixDiagonal(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A)
void givapp(SC *c, SC *s, SC *v, int k) const
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)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Constraint space information for the potential prolongator.
void swap(RCP< T > &r_ptr)
RCP< const CrsGraph > GetPattern() const
Print even more statistics.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
#define I(i, j)
void Iterate(const Matrix &A, const Constraint &C, const Matrix &P0, RCP< Matrix > &P) const
Iterate.
void Apply(const Matrix &P, Matrix &Projected) const
Apply constraint.
Scalar SC
Exception throws to report errors in the internal logical of the program.
static Scalar Frobenius(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &B)